获取对数组内部结构的引用

时间:2011-08-20 18:41:36

标签: c# arrays struct ref

我想修改数组内部的结构字段,而不必设置整个结构。在下面的示例中,我想在数组中设置元素543的一个字段。我不想复制整个元素(因为复制MassiveStruct会损害性能)。

class P
{
    struct S
    {
      public int a;
      public MassiveStruct b;
    }

    void f(ref S s)
    {
      s.a = 3;
    }

    public static void Main()
    {
      S[] s = new S[1000];
      f(ref s[543]);  // Error: An object reference is required for the non-static field, method, or property
    }
}

有没有办法在C#中做到这一点?或者我总是要从数组中复制整个结构,修改副本,然后将修改后的副本放回到数组中。

3 个答案:

答案 0 :(得分:10)

唯一的问题是您尝试从静态方法调用实例方法,而不使用P的实例。

f成为一个静态方法(或创建一个P的实例来调用它),它会没问题。这都是关于阅读编译器错误:))

话虽如此,我强烈建议你:

  • 尽可能避免创建大量结构
  • 尽可能避免创建可变结构
  • 避免使用公共字段

答案 1 :(得分:2)

虽然Jon Skeet对于您的程序无法编译的原因是正确的,但您可以这样做:

s[543].a = 3;

...它将直接在数组中的结构上运行,而不是在副本上运行。

请注意,此提示仅适用于数组,其他集合(如列表)将从indexer-getter返回一个副本(如果您在结果值上尝试类似的操作,则会给出编译器错误) 。

另一方面,mutable structs are considered evil。您是否有充分的理由不想让S成为一个班级?

答案 2 :(得分:0)

您可以尝试使用不包含实际数据的forwarding empty struc t,但只保留dataprovider对象的索引。这样,您可以存储大量数据,而不会使对象图复杂化。 我非常肯定,只要您不尝试将其编组为非托管代码,在您的情况下使用转发emtpy结构替换您的巨型结构应该非常容易。

看看这个结构。它可以包含尽可能多的数据。诀窍在于您将实际数据存储在另一个对象中。通过这种方式,您可以获得引用语义和结构的优势,这些结构比类对象消耗更少的内存,并且由于更简单的对象图(如果您有许多实例(数百万))而更快的GC循环。

    [StructLayout(LayoutKind.Sequential, Pack=1)]
    public struct ForwardingEmptyValueStruct
    {
        int _Row;
        byte _ProviderIdx;


        public ForwardingEmptyValueStruct(byte providerIdx, int row)
        {
            _ProviderIdx = providerIdx;
            _Row = row;
        }

        public double V1
        {
            get { return DataProvider._DataProviders[_ProviderIdx].Value1[_Row];  }
        }

        public int V2
        {
            get { return DataProvider._DataProviders[_ProviderIdx].Value2[_Row];  }
        }
    }