c# - 存储对结构数组的 C# 引用并检索它 - 可以不复制吗?

标签 c# arrays struct

更新:下一个版本的 C# 有一个正在考虑中的功能,可以直接回答这个问题。比较答案如下。


要求:

  1. 应用程序数据存储在结构数组中。应用程序中的每种数据类型都有一个 AoS(例如,一个用于 MyStruct1,另一个用于 MyStruct2,等等)
  2. 结构是在运行时创建的;我们在应用程序中编写的代码越多,就会越多。
  3. 我需要一个类来保存对所有 AoS 的引用,并允许我在这些 AoS 中设置和获取各个结构
  4. 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/

相关文章:

javascript - 使用 javascript .filter() 删除重复的对象

php - 在 foreach 中查询没有结果

c - 将字符串分配给常量结构

c# - 带有静态字段的 Switch 语句

c# - WPF:在没有清除/添加的情况下替换数据绑定(bind)集合内容

c# - C# 中的 Chrome 控制台登录

python - 使用 SWIG 将 C 结构数组访问到 Python

c# - 为什么递增 Nullable<int> 不会抛出异常?

python - 如何在Python中的字符串数组中附加管道分隔符

c++ - 为什么结构的 sizeof 不等于每个成员的 sizeof 之和?