C# 7 中的 C# 匿名类型是否多余
Are C# anonymous types redundant in C# 7
自从 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();
多余。
哪个用例比另一个更好用(出于性能原因或优化原因)?
显然,如果需要超过六个字段,则不能使用元组,但是有没有更细微的差别?
匿名类型和 C# 7 元组之间存在各种差异,在某些情况下可能会或可能不会使一个比另一个更合适:
- C# 7 元组是
ValueTuple<>
。这意味着它们是 值类型 而匿名类型是引用类型。
- 元组允许在编译时进行静态类型化,因为它们是一种可以显式表达的类型。因此,您可以将它们用作方法参数、return 类型等。
- 匿名类型的成员是存在于该类型上的实际属性。元组项是 字段 .
- 匿名类型的属性具有实际名称,而元组中的字段仅命名为
ItemN
(对于数字 N
)。标签只是编译器主要使用的元数据信息,不会与实际的元组对象一起保存。
- 因为创建匿名类型实际上在幕后创建了一个类型,所以您对它们具有一定程度的类型安全性。由于元组只是具有应用类型参数的通用容器,因此您对它们没有完全的类型安全。例如 size 的
(int, int)
元组将完全兼容 position 的 (int, int)
元组,而匿名类型完全关闭。
- 正如 Jon Skeet 提到的,C# 7 元组语法在表达式树中是 currently not supported。
@poke 的当前回答是正确的,并指出了元组和匿名类型之间的区别。我将讨论为什么您仍然会使用它们或更喜欢其中一个。
有两个新的 c# 7 特性可以淘汰匿名类型。 ValueTuples and Records.
您不使用匿名类型的主要原因是
- 您不能在全局范围内使用匿名类型,它们只有在本地使用时才是类型安全的。不是本地的,您必须将其视为
dynamic
具有显着性能开销的对象
您更喜欢元组而不是匿名类型的原因。
它们在所有地方都是类型安全的。 (不考虑命名)
它们可以用作方法参数、类型参数、字段以及几乎所有地方。 (是的,我说的差不多了,有些地方需要采用元组,这是时间问题。)
因为它们可以用作类型参数,您可能更喜欢将轻量级参数集包装在单个参数中。喜欢 Stack<(min, mid, max)>
你可以在你觉得合适的时候更改项目命名,在通用上下文中名称 item
可能会满足,在更具体的上下文中你也需要更具体的名称,比如 car
它们是隐式可转换的,int, int
可以分配给 (int, long)
而无需显式转换。
它们在 Deconstruct 中使用。这给语言带来了很多语法糖。
你可以有多个赋值和声明,比如(int x, int y) = (0, 1)
拥有所有这些功能,还有一个原因可能会让您更喜欢匿名类型而不是元组。
- 匿名类型是引用类型,而元组是值类型。
但是如果你想全局使用匿名类型怎么办?您更喜欢动态对象还是静态类型对象?
传入记录功能再次击败匿名类型。使用记录,您可以用简短、简洁和方便的方式定义 class。没什么大不了的。只有一行
public class Point(X, Y);
无处不在的类型安全,而且您还掌握了引用类型。这两个新特性带来了击败匿名类型的一切。
请注意,记录尚未添加,我们只需要等待。
仅剩下的匿名类型的实际使用将是
它们仍然作为向后兼容的功能
当您在本地使用匿名类型时,它们可以在 Linq 查询中使用。因此我并不是说匿名类型是多余的。
正如我所说,ValueTuples 还不兼容所有组件。这只是时间问题,但这就是未来的样子。
足够的论据。在我看来,匿名类型的使用变得很少,老程序员可能仍然习惯在 Linq 中使用匿名类型。
自从 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();
多余。
哪个用例比另一个更好用(出于性能原因或优化原因)?
显然,如果需要超过六个字段,则不能使用元组,但是有没有更细微的差别?
匿名类型和 C# 7 元组之间存在各种差异,在某些情况下可能会或可能不会使一个比另一个更合适:
- C# 7 元组是
ValueTuple<>
。这意味着它们是 值类型 而匿名类型是引用类型。 - 元组允许在编译时进行静态类型化,因为它们是一种可以显式表达的类型。因此,您可以将它们用作方法参数、return 类型等。
- 匿名类型的成员是存在于该类型上的实际属性。元组项是 字段 .
- 匿名类型的属性具有实际名称,而元组中的字段仅命名为
ItemN
(对于数字N
)。标签只是编译器主要使用的元数据信息,不会与实际的元组对象一起保存。 - 因为创建匿名类型实际上在幕后创建了一个类型,所以您对它们具有一定程度的类型安全性。由于元组只是具有应用类型参数的通用容器,因此您对它们没有完全的类型安全。例如 size 的
(int, int)
元组将完全兼容 position 的(int, int)
元组,而匿名类型完全关闭。 - 正如 Jon Skeet 提到的,C# 7 元组语法在表达式树中是 currently not supported。
@poke 的当前回答是正确的,并指出了元组和匿名类型之间的区别。我将讨论为什么您仍然会使用它们或更喜欢其中一个。
有两个新的 c# 7 特性可以淘汰匿名类型。 ValueTuples and Records.
您不使用匿名类型的主要原因是
- 您不能在全局范围内使用匿名类型,它们只有在本地使用时才是类型安全的。不是本地的,您必须将其视为
dynamic
具有显着性能开销的对象
您更喜欢元组而不是匿名类型的原因。
它们在所有地方都是类型安全的。 (不考虑命名)
它们可以用作方法参数、类型参数、字段以及几乎所有地方。 (是的,我说的差不多了,有些地方需要采用元组,这是时间问题。)
因为它们可以用作类型参数,您可能更喜欢将轻量级参数集包装在单个参数中。喜欢
Stack<(min, mid, max)>
你可以在你觉得合适的时候更改项目命名,在通用上下文中名称
item
可能会满足,在更具体的上下文中你也需要更具体的名称,比如car
它们是隐式可转换的,
int, int
可以分配给(int, long)
而无需显式转换。它们在 Deconstruct 中使用。这给语言带来了很多语法糖。
你可以有多个赋值和声明,比如
(int x, int y) = (0, 1)
拥有所有这些功能,还有一个原因可能会让您更喜欢匿名类型而不是元组。
- 匿名类型是引用类型,而元组是值类型。
但是如果你想全局使用匿名类型怎么办?您更喜欢动态对象还是静态类型对象?
传入记录功能再次击败匿名类型。使用记录,您可以用简短、简洁和方便的方式定义 class。没什么大不了的。只有一行
public class Point(X, Y);
无处不在的类型安全,而且您还掌握了引用类型。这两个新特性带来了击败匿名类型的一切。
请注意,记录尚未添加,我们只需要等待。
仅剩下的匿名类型的实际使用将是
它们仍然作为向后兼容的功能
当您在本地使用匿名类型时,它们可以在 Linq 查询中使用。因此我并不是说匿名类型是多余的。
正如我所说,ValueTuples 还不兼容所有组件。这只是时间问题,但这就是未来的样子。
足够的论据。在我看来,匿名类型的使用变得很少,老程序员可能仍然习惯在 Linq 中使用匿名类型。