如何在C#中访问类似数组的结构的成员?

时间:2011-07-19 16:01:17

标签: c# struct field

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

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

谢谢!

5 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

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

我会修改下面的代码示例以使用带有常量的正确属性名称,但是如果您知道属性名称,则只需直接调用属性并从反射开销中保存自己。否则,请使用带常量的字典。

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

我可能会陷入地狱,但是......

显然非常糟糕,不推荐使用,只有在您的字段全部为默认布局的情况下才有效...

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));
    }
}

答案 4 :(得分:-1)

您可以在.NET BUT中执行此操作,因为其他几个人已经发布了:不要这样做。

一些代码

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

编辑: 有几个原因没有这样做:

  • 订单无法保证!

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

  • readonly属性会发生什么?

再次:不要这样做!