假设我有一个结构,其中包含超过一百个具有复杂名称的元素。我正在使用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;"
}
谢谢!
答案 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属性会发生什么?
再次:不要这样做!