How to access members of an struct like an array i

2020-05-02 02:51发布

Lets say I have a struct with more than hundred elements with complex names. And I am passing a struct of the struct type described to a function using ref, like this:

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

Thanks!

标签: c# struct field
5条回答
放荡不羁爱自由
2楼-- · 2020-05-02 03:06

Maybe you should re-examine your choice of data structure. Perhaps a dictionary would be better suited?

查看更多
走好不送
3楼-- · 2020-05-02 03:13

It's a strange request as you're expecting the order of the fields to be significant, but I suspect you could do this through Reflection or the TypeDescriptor.

I would revise my code sample below to use proper property names with constants, but if you know the property names, just call the properties directly and save yourself from the reflection overhead. Otherwise, use a dictionary with constants.

/* yeah, probably not a good idea.
public void Foo(ref MyStruct a)
{
    TypeDescriptor.GetProperties(a)[0].SetValue(a, 10);
}
*/
查看更多
小情绪 Triste *
4楼-- · 2020-05-02 03:15

While you can use the struct LayoutKind attribute to force simple types to share memory like a "C" Union, you still cannot make an array share memory with simple types because ref types (aka garbage collected types) don't work with the attribute. The concept of C shortcuts like memset of a struct don't map to C# in any way, because C# is a safe language. In fact, that is a Good Thing. Many bugs have come from these kinds of memory addressing shortcuts.

If you want to simulate this behavior, create a class with properties that map to specific members of a backing array, but again, why do this? There are much better data structures to suit your needs in C# such as List, SortedList, Dictionary, Map, Stack, etc. that are safe.

查看更多
狗以群分
5楼-- · 2020-05-02 03:17

You can do this in .NET BUT as several others have already posted: DO NOT DO IT.

Some Code

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

EDIT: several reasons not to do this:

  • the order is not guaranteed !

  • what happens when there are no properties ?

  • what happens with readonly properties ?

So again: DO NOT DO THIS!

查看更多
老娘就宠你
6楼-- · 2020-05-02 03:23

I will probably burn in hell, but...

Obviously horrible and not recommended and only works if your fields are all ints with default layout...

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));
    }
}
查看更多
登录 后发表回答