如何同时移动两个枚举器?

时间:2018-12-18 19:27:39

标签: c# .net struct ref

我有两个包含两个只读结构的大数组:A和B。我需要枚举它们,但是我需要以最优化的方式进行操作。

readonly struct A {
   long a;
   long b;
   long c;
   long d;
   long e;
   long g;
}

readonly struct B {
   byte a;
   ushort b;
}

如您所见,类型A非常大struct,可以一遍又一遍地复制它,因此我制作了自定义枚举器,该枚举器通过引用(struct)返回了此ref return。类型B不需要它,因为它的大小只有4个字节。现在,我只需要使用单个foreach循环就可以使两个枚举器同时移动,因为直接调用Enumerator的方法(即MoveNext,Current)看起来并不像本地调用那样。

我的问题是,当我尝试将两个结构保存在一个聚合中时,struct A被复制,而我的性能损失也消失了。

public readonly struct Aggregate
{
    public readonly A ItemA;
    public readonly B ItemB;

    public Aggregate(A itemA, in B itemB)
    {
        ItemA = itemA;
        ItemB = itemB;
    }
}

此聚合的总大小为56个字节。当我将结构分配给另一个结构的属性时,C#复制该结构听起来很合逻辑。但是我该怎么办?我只需要引用数组的元素。我认为,使用不安全的代码获取指针不是正确的方法,因为GC可以移动我的数组(如果数组足够小并且不在LOH区域中)。

那么您可以向我提出什么解决方案?

2 个答案:

答案 0 :(得分:1)

我不知道我是否理解您的问题正确,但是您在谈论数组。

假设:两者都是大小相同的数组

你可以做到

for (int i = 0; i < length; i++)
{
    ref var aItem = ref arrayA[i];
    ref var bItem = ref arrayB[i];
    //do your stuff
}

答案 1 :(得分:0)

您可以显式使用枚举器,而无需foreach循环:

var aEnumerator = listA.GetEnumerator();
var bEnumerator = listB.GetEnumerator();
while (aEnumerator.MoveNext() && bEnumerator.MoveNext()) {
    var aItem = aEnumerator.Current;
    var bItem = bEnumerator.Current;
    //TODO: do some work
}