将C#引用存储到结构数组并检索它 - 可以不复制?

Ada*_*dam 5 c# arrays struct

更新:下一版本的C#有一个正在考虑的功能,可以直接回答这个问题.cf下面的答案.


要求:

  1. 应用程序数据存储在结构数组中.应用程序中的每种类型的数据都有一个AoS(例如,一个用于MyStruct1,另一个用于MyStruct2等)
  2. 结构在运行时创建; 我们在应用程序中编写的代码越多,就会越多.
  3. 我需要一个类来保存对所有AoS的引用,并允许我在这些AoS中设置和获取单独的结构
  4. AoS往往很大(每个阵列有1000个结构); 复制那些AoS将彻底失败 - 它们永远不应被复制!(他们永远不需要!)

我有编译和运行的代码,它的工作原理......但是每当我访问A#时,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;
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 我需要确保C#将其视为一个值类型数组,而不是一个对象数组("你不要在我的结构周围制作一个盒装对象数组!").据我了解:Generic T []确保(如预期的那样)
  • 我无法弄清楚如何表达类型"这将是一个结构数组,但我不能告诉你编译时哪些结构"除了System.Array.System.Array 有效 - 但也许有其他选择?
  • 为了索引生成的数组,我必须回输到T [].我很害怕,这种类型转换MIGHT被拳击的排列,结构体; 我知道如果它是(T)而不是(T []),那肯定是盒子; 希望T []没有这样做?
  • 或者,我可以使用System.Array方法,它绝对包装传入和传出结构.这是一个相当大的问题(虽然我可以解决它,如果是使C#与Array-of-struct一起工作的唯一方法)

Ale*_*lex 3

据我所知,您正在做的事情应该可以正常工作,但是,是的,T当您调用 时,它会返回结构实例的副本Get,并在您调用 时使用基于堆栈的实例执行替换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]);
}
Run Code Online (Sandbox Code Playgroud)

或者简单地返回对底层数组本身的引用,如果您不需要抽象它/隐藏您的类封装它们的事实:

public T[] GetArray<T>()
{
    return (T[])structArraysByType[typeof(T)];
}
Run Code Online (Sandbox Code Playgroud)

然后您可以从中简单地访问元素:

var myThingsArray = MyStructArraysType.GetArray<MyThing>();
var someFieldValue = myThingsArray[10].SomeField;
myThingsArray[3].AnotherField = "Hello";
Run Code Online (Sandbox Code Playgroud)

或者,如果没有特定原因将它们设为结构(即确保顺序缓存友好的快速访问),您可能只想使用类。