如何访问像C#中的数组这样的结构的成员?

如何访问像C#中的数组这样的结构的成员?,c#,struct,field,C#,Struct,Field,假设我有一个结构,它有100多个具有复杂名称的元素。我使用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多个具有复杂名称的元素。我使用ref将所述结构类型的结构传递给函数,如下所示:

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

谢谢

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

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

这是一个奇怪的请求,因为您希望字段的顺序是重要的,但我怀疑您可以通过反射或TypeDescriptor来实现这一点

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

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

这是一个奇怪的请求,因为您希望字段的顺序是重要的,但我怀疑您可以通过反射或TypeDescriptor来实现这一点

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

/* yeah, probably not a good idea.
public void Foo(ref MyStruct a)
{
    TypeDescriptor.GetProperties(a)[0].SetValue(a, 10);
}
*/
虽然可以使用该属性强制简单类型像“C”联合一样共享内存,但仍然无法使数组与简单类型共享内存,因为ref类型(也称为垃圾收集类型)不使用该属性。C快捷方式的概念,如结构的memset,无论如何都不会映射到C,因为C是一种安全的语言。事实上,这是一件好事。许多错误都来自于这些类型的内存寻址快捷方式

如果要模拟此行为,请创建一个具有映射到支持数组的特定成员的属性的类,但同样,为什么要这样做?在C#中有更好的数据结构来满足您的需要,例如列表、分类列表、字典、映射、堆栈等,它们都是安全的。

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


如果要模拟此行为,请创建一个具有映射到支持数组的特定成员的属性的类,但同样,为什么要这样做?在C语言中,有更好的数据结构可以满足您的需要,例如列表、分类列表、字典、地图、堆栈等,它们都是安全的。

我可能会下地狱,但是

很明显,这很可怕,不推荐使用,只有当您的字段都是int且具有默认布局时才有效

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

我可能会在地狱里被烧死,但是

很明显,这很可怕,不推荐使用,只有当您的字段都是int且具有默认布局时才有效

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

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

一些代码

a.GetType().GetProperties() [0].SetValue (a, newvalue, null);
编辑: 不这样做的几个原因:

  • 订单不能保证

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

  • 只读属性会发生什么情况


所以再说一遍:不要这样做

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

一些代码

a.GetType().GetProperties() [0].SetValue (a, newvalue, null);
编辑: 不这样做的几个原因:

  • 订单不能保证

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

  • 只读属性会发生什么情况



所以再说一遍:不要这样做

为什么要有一个包含100个字段的结构?可以使用反射来确定条目,但不能这样做。这是错误的@Yossarian是对的。A:可变结构是邪恶的B:结构的大小应该是合理的(
ref
是一种黑客的解决方法)。除非你有一个非常专业的场景,否则这不是一个很好的设计方法……它不是100,而是26。我只是想说明结构有很多字段。我很确定这是一些遗留C代码的端口(就像你的另一个问题一样)。移植的一部分是意识到什么时候做得不好并修复它。在这种情况下,数组比保留
struct
更有意义。正如前一个问题中的SLaks所建议的那样,如果您觉得有必要,请将数组包装在一个具有适当属性getter/setter的类中。为什么要有一个包含100个字段的结构?您可以使用反射来确定条目,但不能这样做。这是错误的@Yossarian是对的。A:可变结构是邪恶的B:结构的大小应该是合理的(
ref
是一种黑客的解决方法)。除非你有一个非常专业的场景,否则这不是一个很好的设计方法……它不是100,而是26。我只是想说明结构有很多字段。我很确定这是一些遗留C代码的端口(就像你的另一个问题一样)。移植的一部分是意识到什么时候做得不好并修复它。在这种情况下,数组比保留
struct
更有意义。正如前一个问题中推荐的SLaks,如果您觉得需要,可以使用适当的属性getter/setter将数组包装在一个类中。属性不会以任何定义的顺序显式报告。MSDN对此很清楚。谢谢Marc,还有支持这个的链接:wth?人们对我的更新版本投了反对票,认为这是个坏主意?谢谢各位,你们都是学者。属性不会以任何定义的顺序显式报告。MSDN对此很清楚。谢谢Marc,还有支持这个的链接:wth?人们对我的更新版本投了反对票,认为这是个坏主意?谢谢各位,你们都是学者。正如已经指出的,你们不能保证a的顺序属性是什么