15

由于 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();

多余的。

一个比另一个更好使用的用例(出于性能原因或优化)会是什么用例?

显然,如果需要超过六个字段,则不能使用元组,但是有什么更细微的地方吗?

4

2 回答 2

13

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

  • C# 7 元组是ValueTuple<>s。这意味着它们是值类型,而匿名类型是引用类型。
  • 元组允许在编译时进行静态类型化,因为它们是一种可以显式表达的类型。因此,您可以将它们用作方法参数、返回类型等。
  • 匿名类型的成员是存在于该类型上的实际属性。元组项是字段
  • 匿名类型的属性有一个实际名称,而元组上的字段只是命名ItemN(对于 numbers N)。标签只是编译器主要使用的元数据信息,并没有与实际的元组对象一起保存。
  • 因为创建匿名类型实际上是在底层创建了一个类型,所以您对它们具有一定的类型安全性。由于元组只是具有应用类型参数的通用容器,因此您没有完全的类型安全性。例如,大小(int, int)的元组将与位置的元组完全兼容,而匿名类型则完全关闭。(int, int)
  • 正如 Jon Skeet 所提到的,表达式树目前不支持C# 7 元组语法。
于 2017-07-01T15:39:23.347 回答
0

@poke 当前的答案是正确的,并指出了元组和匿名类型之间的区别。我将讨论为什么您仍会使用它们或更喜欢其中一个。

有两个新的 c# 7 功能淘汰了匿名类型。值元组记录

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

  • 您不能全局使用匿名类型,它们仅在本地使用时是类型安全的。不是本地的,您必须将其视为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 中使用匿名类型。

于 2017-10-24T06:23:56.050 回答