C#:循环遍历嵌套结构的成员对象

     2023-02-18     82

关键词:

【中文标题】C#:循环遍历嵌套结构的成员对象【英文标题】:C#: Looping through member objects of nested structs 【发布时间】:2021-12-27 18:06:42 【问题描述】:

大家好,所有 c# 向导!

我需要将(打包的)嵌套结构的所有内存偏移值存储在这些各自的结构中。 到目前为止,循环遍历所有成员都可以正常工作。另外,我得到了适当的内存偏移值。 这个结构装置可能包含几十个结构,最后还有几百个其他成员。 但是我在初始化时做这一切,所以 CPU 性能在这里不会成为问题。


但是:

在这个迭代过程中,我似乎无法访问这些结构的实际实例。事实证明,当我尝试存储这些偏移值时,它们最终不会出现在我需要它们的地方(当然,我需要它们在实例“SomeStruct1”及其包含其他结构实例中,但是调试器清楚地向我显示了初始值 (-1))。

我怀疑“field_info.GetValue”或“obj_type.InvokeMember”不是获取对象引用的正确方法?还有其他方法可以遍历嵌套结构instances吗?

请帮忙!我已经拼命调试和谷歌了三天,但我现在完全没有想法......

感谢您的努力!

-阿尔伯特


PS - 我做这些不寻常的事情的原因: 我通过提到的嵌套结构在两个嵌入式 CPU 内核之间进行通信(两者都是混合 c/c++ 项目)。这就像一个魅力,因为两个内核共享相同的内存,结构所在的位置。

此外,我必须在 c# 主机应用程序和这些嵌入式内核之间进行通信,所以我认为如果我实现这个结构的第三个实例,这可能是一件很巧妙的事情。只有这一次,我显然不能使用共享 RAM。相反,我为数据保存成员实现值设置器和获取器,找出内存偏移量以及数据保存成员的长度,并通过 USB 或以太网将此信息(连同值本身)提供给嵌入式系统 - 所以我的嵌入式系统的“API”将只是一个结构。每次更改结构时,我必须做的唯一维护是:我必须将保存的 .h 文件(嵌入式项目的)复制到 .cs 文件(宿主项目)。 我知道这很疯狂 - 但现在可以了。

感谢您的关注。 -阿尔伯特


这是一个应该编译和执行的简化(错误,见下文)示例(WinForms,c#7.3):

using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace CodingExample

    public interface Interf
    
        Int32   Offset  get; set; 
    

    [StructLayout (LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    public struct sSomeStruct2 : Interf
    
        public sSomeStruct2 (bool dummy)
        
            Offset      = -1;
            SomeMember3 = 0;
        
        public Int32    Offset  get; set; 
    
        public Int32    SomeMember3;
        // much more various-typed members (e. g. nested structs)...
    

    [StructLayout (LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    public struct sSomeStruct1 : Interf
     
        public sSomeStruct1 (bool dummy)
        
            Offset      = -1;
            SomeMember1 = 0;
            SomeStruct2 = new sSomeStruct2 (true);
            SomeMember2 = 0;
        
        public Int32        Offset  get; set; 

        public Int32        SomeMember1;
        public sSomeStruct2 SomeStruct2;
        public Int16        SomeMember2;
        // much more various-typed members...
    

    public partial class Form1 : Form
    
        void InitializeOffsets (object obj)
        
            Console.WriteLine ("obj: 0", obj);

            Type obj_type   = obj.GetType ();

            foreach (FieldInfo field_info in obj_type.GetFields ())
             
                string field_name   = field_info.Name;
                Int32 offset        = (Int32) Marshal.OffsetOf (obj_type, field_name);
                Type field_type     = field_info.FieldType;
                bool is_leafe       = field_type.IsPrimitive;

// none of theses three options seem to give me the right reference:
//                object node_obj     = field_info.GetValue (obj);
//                object node_obj     = field_info.GetValue (null);
                object node_obj     = obj_type.InvokeMember (field_name, BindingFlags.GetField, null, obj, null);

                Console.WriteLine ("field: 0; field_type: 1; is_leafe: 2; offset: 3", field_name, field_type, is_leafe, offset); 

                if (! is_leafe)
                
// this writes not as expected:                    
                    (node_obj as Interf).Offset = offset;
    
                    InitializeOffsets (node_obj);
                
            
        

        sSomeStruct1 SomeStruct1; 

        public Form1 ()
        
            InitializeComponent ();

            SomeStruct1 = new sSomeStruct1 (true);

            InitializeOffsets (SomeStruct1);
        
    

【问题讨论】:

也许你应该描述你想做什么。你做这一切是为了什么。一定有更好的解决方案,C# 从来没有在内存结构中进行字节推送和偏移计数。 你说的“正确的参考”是什么意思?你有结构。他们被装箱了。传递为object,转换为Interf...新的引用正在被创建和丢弃。您传递给InitializeOffsets 的原始SomeStruct1 正在被复制;原版不受这一切的影响。改用类。 @nvoigt:我同意,必须有更好的解决方案。好的,我将添加一个说明我为什么这样做。 @madreflection:你是对的。我很难避免复制。不幸的是,我需要结构。 【参考方案1】:

同时我发现了我做错了什么:

    我必须做拳击,所以我可以在调用初始化函数时使用“ref”:
// instead of this:
SomeStruct1 = new sSomeStruct1 (true);

// i have to do it this way:
object boxed_SomeStruct1 = new sSomeStruct1 (true);
InitializeOffsets (ref boxed_SomeStruct1);
SomeStruct1 = (sSomeStruct1) boxed_SomeStruct1;

    在“InitializeOffsets”函数中,“field_info.GetValue (obj)”提供了我的成员对象的副本。这就是为什么我必须在 foreach 循环的最后将修改后的副本复制回来:
field_info.SetValue (obj, node_obj);

进行这些更改后,代码将按预期工作。 谢谢你的关注。 -阿尔伯特

【讨论】:

c# 在类嵌套结构中引用非静态类成员

】c#在类嵌套结构中引用非静态类成员【英文标题】:c#referencetonon-staticclassmembersinaclassnestedstruct【发布时间】:2021-10-0616:26:52【问题描述】:我在classC中有一个structS作为嵌套声明,我想在S的构造函数中引用C的成员:publicclassCpri... 查看详情

es6的新特性(14)——iterator和for...of循环(代码片段)

Iterator和for...of循环Iterator(遍历器)的概念JavaScript原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6又添加了Map和Set。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的数据结构,比如数... 查看详情

《es6标准入门》(阮一峰)--17.iterator和for...of循环(代码片段)

...按某种次序排列;三是ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。Iterator的遍历过程是这样的。(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对... 查看详情

iterator(遍历器)(代码片段)

...某种次序排练;三是ES6创造了一种新的遍历命令---for...of循环,Iterator接口主要提供for...of消费。Iterator的遍历过程如下。1.创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上就是一个指针对象。2.第... 查看详情

如何以对象为成员循环遍历纯 JavaScript 对象

】如何以对象为成员循环遍历纯JavaScript对象【英文标题】:HowtoloopthroughaplainJavaScriptobjectwiththeobjectsasmembers【发布时间】:2010-10-2915:18:52【问题描述】:如何遍历JavaScript对象中的所有成员,包括作为对象的值?例如,我如何循环... 查看详情

循环遍历javascript中对象的所有成员[重复]

】循环遍历javascript中对象的所有成员[重复]【英文标题】:loopthroughtallmembersofanobjectinjavascript[duplicate]【发布时间】:2013-10-1100:31:37【问题描述】:"USA":["country":"Albuquerque(ABQ)","country":"Allentown(ABE)"],"Canada":"country":"Calgary(YYC)"," 查看详情

Node.js 循环遍历嵌套的 Javascript 对象

】Node.js循环遍历嵌套的Javascript对象【英文标题】:Node.jsloopthroughnestedJavascriptobject【发布时间】:2017-04-0811:08:15【问题描述】:我想拥有来自Facebook的帖子和附件,以便创建帖子列表。问题是我想为每个帖子提要将属性:id、消... 查看详情

通过 ASP.NET MVC 在 C# 视图中遍历匿名对象的嵌套 LINQ 查询

】通过ASP.NETMVC在C#视图中遍历匿名对象的嵌套LINQ查询【英文标题】:TraversinganestedLINQqueryinofanonymousobjectsinC#viewviaASP.NETMVC【发布时间】:2010-01-2714:13:55【问题描述】:您好,进行了大量搜索和阅读,但仍需要一些具体信息。我有... 查看详情

python入门之控制结构-循环结构——第3关:循环嵌套(代码片段)

任务描述在python中,除了while循环与for循环,还有循环嵌套。循环嵌套就是在一个循环体里嵌入另一个循环。以下场景便模拟了循环嵌套与跳出循环的现实场景:在一次考试结束后,学校需要统计每位同学的考试总成绩... 查看详情

如何使用 v-for 循环遍历嵌套对象

】如何使用v-for循环遍历嵌套对象【英文标题】:Howtoloopthroughnestedobjectsusingv-forloop【发布时间】:2019-12-0113:37:23【问题描述】:我正在编写一些处理卡片信息的练习代码,您可以在其中通过单击屏幕上的一张卡片来显示所选卡片... 查看详情

循环遍历嵌套的 js 对象并使用 Jquery 使用自定义 html 附加 div

】循环遍历嵌套的js对象并使用Jquery使用自定义html附加div【英文标题】:loopthroughnestedjsobjectandappenddivwithcustomhtmlusingJquery【发布时间】:2021-09-0402:04:51【问题描述】:我什至不确定我是否正确地用了我需要的标题,但简而言之,... 查看详情

iterator(代码片段)

...按某种次序排列;三是ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。  原生具备Iterator接口的数据结构如下。ArrayMapSetStringTypedArray函数的arguments对象NodeList对象 查看详情

445iterator

...能够按某种次序排列3、ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。工作原理:-创建一个指针对象(遍历器对象),指向数据结构的起始位置。-第一次调用next方法,指针自动指向数据结构的第一个成... 查看详情

与复杂/嵌套对象的数据绑定 (C#)

】与复杂/嵌套对象的数据绑定(C#)【英文标题】:DataBindingwithComplex/NestedObjects(C#)【发布时间】:2014-02-0219:35:52【问题描述】:由于我很难找到有关此主题的通用信息,因此我在发布此内容时会尽可能多地进行解释,并希望与SO社... 查看详情

c#设计模式09——组合模式的写法(代码片段)

...文件系统或UI控件。使用该模式,可以将树形数据结构的遍历变得简单且具有一致性,而无论遍历哪个节点,只需按照相同的方式进行。使用组合模式还可以使代码更加灵活。由于容器和叶子节点可以互换使用,可以轻松地添加... 查看详情

15.iterator和for...of循环

  1.Iterator(遍历器)的概念JavaScript原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6又添加了Map和Set。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的数据结构,比如数组的... 查看详情

嵌套循环

Java语言中的各种循环、选择、中断语句和C/C++一般无二。选择结构循环结构中断(跳转)ifforreturnifelsewhilebreakifelseifdowhilecontinueswitchforeach(遍历数组) 这里主要讲一下,for嵌套循环中出现中断(跳转)语句的情况。先看如下... 查看详情

iterator和for...of循环(代码片段)

Iterator(遍历器)的概念JavaScript原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6又添加了Map和Set。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的数据结构,比如数组的成员是Ma... 查看详情