如何访问结构体(如c#中的数组)的成员

本文关键字:何访问 数组 成员 访问 结构体 | 更新日期: 2023-09-27 18:02:44

假设我有一个结构体,它有100多个复杂名称的元素。我用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;"
}

谢谢!

如何访问结构体(如c#中的数组)的成员

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

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

我将修改下面的代码示例,以使用带有常量的适当属性名,但是如果您知道属性名,只需直接调用属性,从而避免反射开销。否则,使用带有常量的字典。
/* yeah, probably not a good idea.
public void Foo(ref MyStruct a)
{
    TypeDescriptor.GetProperties(a)[0].SetValue(a, 10);
}
*/

虽然您可以使用struct LayoutKind属性强制简单类型像"C" Union一样共享内存,但您仍然不能使数组与简单类型共享内存,因为ref类型(又名垃圾收集类型)不能与该属性一起工作。像结构体的memset这样的C快捷方式的概念无论如何都不能映射到c#中,因为c#是一种安全的语言。事实上,这是一件好事。许多错误都来自于这种内存寻址快捷方式。

如果你想模拟这种行为,创建一个类的属性映射到一个后备数组的特定成员,但是,为什么要这样做?c#中有更好的数据结构来满足你的需求,比如List, SortedList, Dictionary, Map, Stack等等,它们都是安全的。

你可以在。net中这样做,但正如其他几个人已经发布的那样:不要这样做。

的一些代码
a.GetType().GetProperties() [0].SetValue (a, newvalue, null);

编辑:不这样做的几个理由:

  • 订单不保证!

  • 如果没有属性会发生什么

所以:不要这样做!

我可能会下地狱,但是…

显然很可怕,不推荐,只有当你的字段都是默认布局的整型时才有效…

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