Как получить доступ к членам структуры, как массив в C #? - PullRequest
0 голосов
/ 19 июля 2011

Допустим, у меня есть структура с более чем сотней элементов со сложными именами. И я передаю структуру типа структуры, описанной функции, используя ref, как это:

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

Спасибо! * * 1004

Ответы [ 5 ]

3 голосов
/ 19 июля 2011

Возможно, вам следует пересмотреть свой выбор структуры данных.Возможно, лучше подойдет словарь?

2 голосов
/ 19 июля 2011

Это странный запрос, поскольку вы ожидаете, что порядок полей будет значимым , но я подозреваю, что вы могли бы сделать это с помощью Reflection или TypeDescriptor.

Я бы пересмотрел мой пример кода ниже, чтобы использовать правильные имена свойств с константами, но если вы знаете имена свойств, просто вызовите свойства напрямую и избавьте себя от накладных расходов на отражение. В противном случае используйте словарь с константами.

/* yeah, probably not a good idea.
public void Foo(ref MyStruct a)
{
    TypeDescriptor.GetProperties(a)[0].SetValue(a, 10);
}
*/
1 голос
/ 19 июля 2011

Несмотря на то, что вы можете использовать атрибут struct LayoutKind , чтобы заставить простые типы совместно использовать память, например, "C" Union, вы все равно не можете сделать массив разделяющим память с простыми типами, потому что ref-типы (то есть типы, собираемые мусором)) не работает с атрибутом.Концепция ярлыков C, таких как memset структуры, никак не связана с C #, потому что C # - безопасный язык.На самом деле, это хорошо.Многие ошибки возникают из-за таких ярлыков адресации памяти.

Если вы хотите смоделировать это поведение, создайте класс со свойствами, которые сопоставляются с конкретными элементами массива поддержки, но опять же, зачем это делать?В C # существуют гораздо лучшие структуры данных, отвечающие вашим потребностям, такие как List, SortedList, Dictionary, Map, Stack и т. Д., Которые безопасны.

0 голосов
/ 19 июля 2011

Вы можете сделать это в .NET, НО, как уже писали несколько других: НЕ ДЕЛАЙТЕ ЭТОГО.

Некоторые коды

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

РЕДАКТИРОВАТЬ: несколько причин этого не делать:1006 *

  • заказ не гарантирован!

  • что происходит при отсутствии свойств?

  • чтопроисходит со свойствами только для чтения?

Итак, еще раз: НЕ ДЕЛАЙТЕ ЭТОГО!

0 голосов
/ 19 июля 2011

Я, вероятно, сгорю в аду, но ...

Очевидно, что это ужасно и не рекомендуется, и работает только в том случае, если все поля имеют целочисленные значения с макетом по умолчанию ...

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