2017-06-30 78 views
11

由于C#7引入了值元组,它们是否有比元组更适合的有意义的场景?C#中的C#匿名类型是多余的7 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(); 

冗余。

对于其中一个更好地用于另一个(用于性能原因或优化)的用例是什么?

很明显,如果需要超过六个字段,元组不会被使用,但有没有更多的细微差别呢?

+3

可读性吗? 'new {x,i}'完全清楚它是一个正在返回的新对象,而我不得不比较这两个例子来找出第一个例子。但那可能就是我。 – stybl

+13

首先,它们在表达式树中支持,而元组文字不是...... –

+7

请注意,您的示例不会在C#7.0中编译,因为'(x,i)'具有未命名的元组元素,但它们是隐式地在C#7.1中命名。 –

回答

12

有匿名类型和C#7元组,其可以是或可以不是在某些情况下使一个比另一个更合适之间的各种差异:

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

好的答案。你会不会包含Jon Skeet关于元组文字不适用于表达式树的观点? –

+0

我喜欢这个答案,因为它提供了有关'ValueTuple's的实现细节。但它仍然没有回答OP问题:匿名类型比“ValueTuple”好吗?第5点(据我所知)更多的是考虑使用普通类型而不是“ValueTuple”。 –

+0

@VadimOvchinnikov是的,当然有场景。这两种功能之间的区别是相关的。 - 如果您需要示例,请使用[Dapper](https://github.com/StackExchange/Dapper),您可以在其中传入带有* named *查询参数的匿名类型。由于元组对象没有关联的名称,因此无法对它们进行此操作。 – poke

1

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

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

,你会不会使用匿名类型的主要原因是

  • 你不能在全球范围使用匿名类型和在本地使用时才会类型安全的。不是地方,你必须把它作为具有显著的性能开销,你喜欢过的元组匿名类型

原因dynamic对象。

  • 他们是在所有地方类型安全。 (不管命名)

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

  • 因为它们可以用作类型参数,所以您可能更喜欢将单个参数中的轻量级参数组包装起来。像Stack<(min, mid, max)>

  • 您可以更改项目命名时,你永远觉得它的相应的,在一般情况下名字item可满足在更具体的情况下,你需要更具体的名字太像car

  • 他们是隐式转换, int, int可以分配给(int, long)而不需要显式转换。

  • 它们用于Deconstruct s。这给语言带来了很多语法糖。

  • 你可以有多个任务和声明一样(int x, int y) = (0, 1)

具有所有这个功能,还有一个原因,你可能更喜欢匿名型过元组。

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

但是如果你想在全局使用匿名类型呢?你喜欢有动态对象还是静态类型的对象?

传入记录功能再次击败匿名类型。通过记录,您可以简短,简洁,方便地定义班级。没什么大不了的。只是一条线

public class Point(X, Y); 

类型安全到处都是,你也有参考类型在手。这两个新功能带来的每一件事都击败了匿名类型。

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

仅存匿名类型的实际使用会

  • 他们仍然作为向后兼容的功能,当你在本地使用匿名类型

  • 他们可以Linq中使用的查询。因此我不会说匿名类型是多余的。

正如我所说ValueTuples与每个组件都不兼容。它只是时间的问题,但未来它将如何。

足够的论据。在我的小见解中,匿名类型的使用变得很少见,旧程序员可能仍然习惯于在Linq中使用匿名类型。