C#7中的C#匿名类型是多余的

时间:2017-06-30 16:23:58

标签: c# compiler-optimization anonymous-types c#-7.0 valuetuple

由于C#7引入了值元组,是否有一个有意义的场景,它们比元组更适合?

例如,以下行

collection.Select((x, i) => (x, i)).Where(y => arr[y.i].f(y.x)).ToArray();

制作以下一行

collection.Select((x, i) => new {x, i}).Where(y => arr[y.i].f(y.x)).ToArray();

多余的。

一个用例比其他用户更好(出于性能原因还是优化)会有什么用?

显然,如果需要超过六个字段,则不能使用元组,但它是否有一些细微之处?

2 个答案:

答案 0 :(得分:12)

匿名类型和C#7元组之间存在各种差异,在某些情况下可能会或可能不会使另一个更合适:

  • C#7元组是ValueTuple<>个。这意味着它们是值类型,而匿名类型是引用类型。
  • 元组允许在编译时进行静态类型,因为它们是可以显式表达的类型。因此,您可以将它们用作方法参数,返回类型等。
  • 匿名类型的成员是该类型上存在的实际属性。元组项是字段
  • 匿名类型的属性具有实际名称,而元组上的字段仅命名为ItemN(对于数字N)。标签只是元数据信息,主要由编译器使用,并不与实际的元组对象保持一致。
  • 因为创建匿名类型实际上会在引擎盖下创建一个类型,所以它们具有一定的类型安全性。由于元组只是具有应用类型参数的通用容器,因此您没有完整的类型安全性。例如, size (int, int)元组与位置(int, int)元组完全兼容,而匿名类型则完全关闭。
  • 正如Jon Skeet所提到的,表达式树中的C#7元组语法为currently not supported

答案 1 :(得分:1)

@poke的当前答案是正确的,并注意元组和匿名类型之间的差异。我将讨论为什么你仍然会使用它们或者更喜欢一个而不是另一个。

有两种新的c#7功能可以退出匿名类型。 ValueTuplesRecords

您不使用匿名类型的主要原因是

  • 您不能全局使用匿名类型,并且在本地使用时它们只是类型安全的。不是本地的,你必须将它视为具有显着性能开销的dynamic对象

您更喜欢使用匿名类型的原因。

  • 它们在所有地方都是类型安全的。 (无论命名如何)

  • 它们可以用作方法参数,类型参数,字段以及几乎每个地方。 (是的,我说的很多,有些地方需要采用元组,这是时间问题。)

  • 因为它们可以用作类型参数,所以您可能更喜欢在单个参数中包含轻量级参数集。比如Stack<(min, mid, max)>

  • 您可以在感觉合适时更改项目命名,在通用上下文名称item中可以满足,在更具体的上下文中,您也需要更具体的名称,例如car

  • 它们是隐式可兑换的,int, int可以在没有明确演员的情况下分配给(int, long)

  • 它们在Deconstruct中使用。这给语言带来了很多语法糖。

  • 您可以拥有多个分配和声明,例如(int x, int y) = (0, 1)

拥有所有这些功能,还有一个原因是你可能更喜欢匿名类型而不是元组。

  • 匿名类型是引用类型,但元组是值类型。

但是如果你想全局使用匿名类型怎么办?你喜欢动态对象还是静态类型对象?

传入的记录功能再次击败匿名类型。通过记录,您可以简洁,方便地定义您的课程。没有大碍。只需一行

public class Point(X, Y);

在整个地方输入安全性,并且您手头也有参考类型。这两个新功能可以打败匿名类型。

请注意,记录尚未添加,我们只需等待。

只有剩余的匿名类型实际使用

  • 它们仍可作为向后兼容功能

  • 当您在本地使用匿名类型时,它们可以在Linq查询中使用。因此,我不是说匿名类型是多余的。

正如我所说,ValueTuples与每个组件都不兼容。这只是时间问题,但这就是未来的情况。

足够的论点。在我看来,匿名类型的使用变得罕见,老程序员可能仍然习惯在Linq中使用匿名类型。