【问题标题】:How to access members of an struct like an array in C#?如何访问结构的成员,如 C# 中的数组?
【发布时间】:2011-07-19 16:01:17
【问题描述】:

假设我有一个结构,其中包含一百多个名称复杂的元素。我正在使用 ref 将描述的结构类型的结构传递给函数,如下所示:

void Foo(ref mystruct a)
{
   "I want to modify members or fields of struct a, like this:
   a[0] = 10;
   a[100] = 11;"
}

谢谢!

【问题讨论】:

  • 为什么要拥有一个包含 100 个字段的结构?
  • 您可以使用反射来确定条目,但不要这样做。这是错误的。 @Yossarian 是对的。
  • A:可变结构是邪恶的 B:结构的大小应该合理(ref 是一种变通的解决方法)。除非你有一个非常专业的场景,否则这不是设计它的好方法......
  • 它不是 100,它正好是 26。我只是为了表明 Struct 有很多字段。
  • 我很确定这是一些遗留 C 代码的移植(正如你的另一个问题是。)移植的一部分是意识到什么时候做得不好并修复它。在这种情况下,数组比保留struct 更有意义。正如 SLaks 在上一个问题中建议的那样,如果您觉得需要,将数组包装在一个具有适当属性 getter/setter 的类中。

标签: c# struct field


【解决方案1】:

也许您应该重新检查您选择的数据结构。也许字典会更合适?

【讨论】:

    【解决方案2】:

    这是一个奇怪的请求,因为您希望字段的顺序很重要,但我怀疑您可以通过 Reflection 或 TypeDescriptor 来做到这一点。

    我将修改下面的代码示例以使用带有常量的正确属性名称,但如果您知道属性名称,只需直接调用属性即可避免反射开销。否则,请使用带有常量的字典。

    /* yeah, probably not a good idea.
    public void Foo(ref MyStruct a)
    {
        TypeDescriptor.GetProperties(a)[0].SetValue(a, 10);
    }
    */
    

    【讨论】:

    • 属性明确不按任何定义的顺序报告。 MSDN 对此很清楚。
    • 感谢 Marc,以及支持这一点的链接:msdn.microsoft.com/en-us/library/aky14axb.aspx
    • 怎么了?人们对我的更新副本投反对票,认为这是一个坏主意?谢谢大家,你们都是学者。
    【解决方案3】:

    虽然您可以使用struct LayoutKind 属性强制简单类型像“C”联合一样共享内存,但您仍然不能使数组与简单类型共享内存,因为引用类型(也称为垃圾收集类型)不起作用与属性。 C 快捷方式(如结构的 memset)的概念不会以任何方式映射到 C#,因为 C# 是一种安全语言。事实上,这是一件好事。许多错误都来自这些类型的内存寻址快捷方式。

    如果您想模拟这种行为,请创建一个具有映射到支持数组的特定成员的属性的类,但同样,为什么要这样做? C# 中有很多更好的数据结构可以满足您的需求,例如安全的 List、SortedList、Dictionary、Map、Stack 等。

    【讨论】:

      【解决方案4】:

      您可以在 .NET 中执行此操作,但正如其他几个人已经发布的那样:不要这样做。

      一些代码

      a.GetType().GetProperties() [0].SetValue (a, newvalue, null);
      

      编辑: 不这样做的几个原因:

      • 订单不保证!

      • 没有属性时会发生什么?

      • 只读属性会发生什么?

      再说一遍:不要这样做!

      【讨论】:

      • 如前所述,使用反射时不能保证返回什么顺序属性,所以不能使用序数。
      • 如果您没有阅读第一行 - 我写了“不要这样做”。我为我的答案添加了一些解释......
      • 我确实阅读了第一行,它没有说明为什么不这样做,而且有人在你之前 22 分钟回答了完全相同的答案......
      【解决方案5】:

      我可能会在地狱中燃烧,但是......

      显然很糟糕,不推荐,只有当您的字段都是具有默认布局的整数时才有效...

      internal class Program
      {
          private struct MyStruct
          {
              //Must be all Int32
              public int Field1, Field2, Field3;
          }
      
          private static void Main()
          {
              MyStruct str = new MyStruct {Field1 = 666, Field2 = 667, Field3 = 668};
      
              int[] array = ToArray(str);
      
              array[0] = 100;
              array[1] = 200;
              array[2] = 300;
      
              str = FromArray(array);
          }
      
          private static int[] ToArray(MyStruct str)
          {
              IntPtr ptr = IntPtr.Zero;
      
              try
              {
                  int size = GetInt32ArraySize(str);
                  int[] array = new int[size];
                  ptr = Marshal.AllocHGlobal(size);
                  Marshal.StructureToPtr(str, ptr, true);
                  Marshal.Copy(ptr, array, 0, size);
                  return array;
              }
              finally
              {
                  Marshal.FreeHGlobal(ptr);
              }
          }
      
          private static MyStruct FromArray(int[] arr)
          {
              IntPtr ptr = IntPtr.Zero;
      
              try
              {
                  MyStruct str = new MyStruct();
                  int size = GetInt32ArraySize(str);
                  ptr = Marshal.AllocHGlobal(size);
                  Marshal.Copy(arr, 0, ptr, size);
                  str = (MyStruct)Marshal.PtrToStructure(ptr, str.GetType());
                  return str;
              }
              finally
              {
                  Marshal.FreeHGlobal(ptr);
              }
          }
      
          private static int GetInt32ArraySize(MyStruct str)
          {
              return Marshal.SizeOf(str) / Marshal.SizeOf(typeof(Int32));
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-06-11
        • 2021-07-12
        • 2020-12-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多