为什么这是作为结构实现的?

时间:2011-06-01 06:36:25

标签: c# linq struct

在System.Data.Linq中,EntitySet<T>使用了几个ItemList<T>结构,如下所示:

 internal struct ItemList<T> where T : class
  {
    private T[] items;
    private int count;
    ...(methods)...
  }

(花了我比发现它更长的时间 - 无法理解为什么EntitySet<T>中的实体字段没有抛出空引用异常!)

我的问题是,将它作为一个类的结构实现它有什么好处?

5 个答案:

答案 0 :(得分:34)

让我们假设您要将ItemList<T>存储在数组中。

分配值类型数组(struct)将数据存储在数组中。另一方面,如果ItemList<T>是引用类型(class),则只有对ItemList<T>个对象的引用才会存储在数组中。实际的ItemList<T>对象将在堆上分配。到达ItemList<T>实例需要额外的间接级别,因为它只是一个与长度相结合的数组,使用值类型会更有效。

Struct vs class

在检查EntitySet<T>的代码后,我可以看到没有涉及数组。但是,EntitySet<T>仍包含两个ItemList<T>个实例。由于ItemList<T>struct,因此这些实例的存储分配在EntitySet<T>对象内。如果使用了classEntitySet<T>将包含指向单独分配的EntitySet<T>个对象的引用。

在大多数情况下,使用其中一个或另一个之间的性能差异可能并不明显,但开发人员可能认为他希望将数组和紧耦合计数视为单个值,因为它似乎是最好的事情

答案 1 :(得分:9)

对于像ItemList<T>这样的小型关键内部数据结构,我们通常可以选择使用引用类型或值类型。如果代码写得很好,从一个代码切换到另一个代码是一个微不足道的变化。

我们可以推测一个值类型可以避免堆分配,而引用类型可以避免结构复制,因此它不会立即清楚,因为它在很大程度上取决于它的使用方式。

找出哪个更好的最好方法是来衡量。无论哪个更快,都是明显的赢家。我确信他们做了基准测试,struct更快了。在你完成这几次之后,你的直觉非常好,基准测试只是证实你的选择是正确的。

答案 2 :(得分:6)

也许重要的是......引用here

中的结构
  

新变量和原始变量   变量因此包含两个   相同数据的单独副本。   对一个副本所做的更改不会影响另一个副本

只是想,不要难以评判我:)

答案 3 :(得分:5)

使用结构实际上只有两个原因,那就是获取值类型语义,或者获得更好的性能。

由于struct包含一个数组,因此值类型语义不能正常工作。复制结构时,您将获得count的副本,但只获得对数组的引用的副本,而不是数组中项目的副本。因此,每当复制结构时都必须特别小心,这样就不会得到不一致的实例。

因此,唯一剩下的正当理由是表现。每个引用类型实例都有一个很小的开销,所以如果你有很多它们,可能会有明显的性能提升。

这种结构的一个很好的特性是你可以创建它们的数组,并且你得到一个空列表数组而不必初始化每个列表:

ItemList<string>[] = new ItemList<string>[42];

由于数组中的项是零填充的,count成员将为零,items成员将为null。

答案 4 :(得分:2)

纯粹猜测:

由于对象相当小(只有两个成员变量),因此将struct作为ValueType进行传递是一个很好的选择。

另外,正如@Martin Liversage指出的那样,通过成为ValueType,它可以更有效地存储在更大的数据结构中(例如作为数组中的项目),而不会产生单个对象和参考它。