更新:下一个版本的 C# 有一个正在考虑中的功能,可以直接回答这个问题。比较答案如下。
要求:
- 应用程序数据存储在结构数组中。应用程序中的每种数据类型都有一个 AoS(例如,一个用于 MyStruct1,另一个用于 MyStruct2,等等)
- 结构是在运行时创建的;我们在应用程序中编写的代码越多,就会越多。
- 我需要一个类来保存对所有 AoS 的引用,并允许我在这些 AoS 中设置和获取各个结构
- AoS 往往很大(每个数组有 1,000 个结构);复制那些 AoS 将彻底失败——永远不应该复制它们! (他们永远不需要!)
我有可以编译和运行的代码,而且它可以工作……但是 C# 是否会在我每次访问它们时默默地复制 AoS? (完整来源见下文)
public Dictionary<System.Type, System.Array> structArraysByType;
public void registerStruct<T>()
{
System.Type newType = typeof(T);
if( ! structArraysByType.ContainsKey(newType ) )
{
structArraysByType.Add(newType, new T[1000] ); // allowing up to 1k
}
}
public T get<T>( int index )
{
return ((T[])structArraysByType[typeof(T)])[index];
}
public void set<T>( int index, T newValue )
{
((T[])structArraysByType[typeof(T)])[index] = newValue;
}
注意事项:
- 我需要确保 C# 将其视为一个值类型数组,而不是一个对象数组(“你敢在我的结构周围制作一个装箱对象数组吗!”)。据我了解:Generic T[] 确保(如预期的那样)
- 除了 System.Array,我不知道如何表达“这将是一个结构数组,但我无法在编译时告诉你哪些结构”的类型。 System.Array 有效——但也许还有其他选择?
- 为了索引结果数组,我必须类型转换回 T[]。我担心这种类型转换可能 会封装结构数组;我知道如果它是 (T) 而不是 (T[]),它肯定会 box;希望它不会对 T[] 这样做?
- 或者,我可以使用 System.Array 方法,它肯定会包含传入和传出结构。这是一个相当大的问题(尽管如果这是使 C# 与 Array-of-struct 一起工作的唯一方法,我可以解决它)
最佳答案
据我所知,您正在做的事情应该可以正常工作,但是是的,当您调用 Get
时,它会返回结构 T
实例的副本,并且当您调用 Set
时,使用基于堆栈的实例执行替换。除非您的结构很大,否则这应该不是问题。
如果它们很大而你想要
- 读取数组中结构实例之一的(某些)属性,而不创建它的副本。
- 更新它的一些字段(你的结构不应该是不可变的,这通常是个坏主意,但这样做有充分的理由)
然后您可以将以下内容添加到您的类中:
public delegate void Accessor<T>(ref T item) where T : struct;
public delegate TResult Projector<T, TResult>(ref T item) where T : struct;
public void Access<T>(int index, Accessor<T> accessor)
{
var array = (T[])structArraysByType[typeof(T)];
accessor(ref array[index]);
}
public TResult Project<T, TResult>(int index, Projector<T, TResult> projector)
{
var array = (T[])structArraysByType[typeof(T)];
return projector(ref array[index]);
}
或者简单地返回对底层数组本身的引用,如果你不需要抽象它/隐藏你的类封装它们的事实:
public T[] GetArray<T>()
{
return (T[])structArraysByType[typeof(T)];
}
然后您可以从中简单地访问元素:
var myThingsArray = MyStructArraysType.GetArray<MyThing>();
var someFieldValue = myThingsArray[10].SomeField;
myThingsArray[3].AnotherField = "Hello";
或者,如果没有特定原因将它们作为结构(即确保顺序缓存友好的快速访问),您可能只想使用类。
关于c# - 存储对结构数组的 C# 引用并检索它 - 可以不复制吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30006048/