为什么.NET中的匿名类型实现为引用类型?

时间:2011-08-18 14:31:07

标签: .net linq performance anonymous-types value-type

因为无论如何匿名类型是只读的,如果它们作为结构实现它们会更有效,因此linq查询不需要创建大量的临时对象:

// This doesn't make any sense, it is just for demonstration
var result = thingies
.Select(x=> new {A = 1, B = 2, C = 3});

顺便说一下。当reading this

时,我明白了这个想法

修改

最好的事情是,如果编译器将根据变量的大小和用法(必须传递给许多方法),决定是否生成值类型或引用类型。

但是我在msdn中找到的以下句子会导致问题:

  

如果同一程序集中的两个或多个匿名类型具有相同的类型   编译器处理的属性的数量和类型,顺序相同   它们是同一类型。

由于匿名对象(及其关联类型)无法离开定义它的方法,我们在这里没有问题,是吗?

2 个答案:

答案 0 :(得分:6)

完整的.NET垃圾收集器针对两种情况进行了特别优化:持续大量时间的大型长寿命对象,以及快速死亡的小型,短期对象。 Gen0系列实际上是免费的,因为它们有多快(如此快速和频繁,事实上,许多剖析器甚至不打扰显示它们或它们的内容),所以没有理由避免临时工作在范围内消失创建它们的功能。

匿名类型几乎完美地适合第二种情况;它们并不意味着比创建它们的功能更长(尽管你可以用一些技巧来做)。鉴于这个模型,并且鉴于大多数值类型的复制相对昂贵,并且鉴于许多LINQ查询涉及需要另一个副本的长链函数,我认为设计师选择制作他们引用类型。

答案 1 :(得分:1)

如果匿名类型是值类型,我确信我可以制作一些基准测试,显示所有复制是多么可怕,以及它们应该如何成为引用类型,以便它们不需要在任何地方复制。两种方法都有好处和权衡,语言设计者选择使用参考类型;我怀疑,因为引用类型更常见,更容易理解,并且使用比值类型更多的API。

但是,最高速度并不是匿名类型的重点。它们是为90%的开发人员构建的,这些开发人员需要使用中间类型来存储结果的合理大小的LINQ查询。对于需要数百万个对象的10%,我建议他们创建一个具体类型并投入一些优化时间。