推理 (的元组名称。Infer tuple names (aka. 元组投影初始值设定项) tuple projection initializers)

总结Summary

在许多常见情况下,此功能允许忽略元组元素名称,而不是推断。In a number of common cases, this feature allows the tuple element names to be omitted and instead be inferred. 例如, (f1: x.f1, f2: x?.f2) 可以从推断元素名称 "f1" 和 "f2",而不是键入 (x.f1, x?.f2)For instance, instead of typing (f1: x.f1, f2: x?.f2), the element names "f1" and "f2" can be inferred from (x.f1, x?.f2).

这与匿名类型的行为类似,允许在创建过程中推断成员名称。This parallels the behavior of anonymous types, which allow inferring member names during creation. 例如, new { x.f1, y?.f2 } 声明成员 "f1" 和 "f2"。For instance, new { x.f1, y?.f2 } declares members "f1" and "f2".

在 LINQ 中使用元组时,此操作特别有用:This is particularly handy when using tuples in LINQ:

// "c" and "result" have element names "f1" and "f2"
var result = list.Select(c => (c.f1, c.f2)).Where(t => t.f2 == 1); 

详细设计Detailed design

更改包括两个部分:There are two parts to the change:

  1. 尝试为没有显式名称的每个元组元素推断候选名称:Try to infer a candidate name for each tuple element which does not have an explicit name:
    • 使用与匿名类型的名称推理相同的规则。Using same rules as name inference for anonymous types.
      • 在 c # 中,这允许以下三种情况: y (标识符) 、 x.y (简单成员访问) 和 x?.y (条件访问) 。In C#, this allows three cases: y (identifier), x.y (simple member access) and x?.y (conditional access).
      • 在 VB 中,这可以实现其他情况,如 x.y()In VB, this allows for additional cases, such as x.y().
    • 在 c # 中拒绝保留元组名称 (区分大小写,在 VB) 中不区分大小写,因为它们被禁止或已隐式。Rejecting reserved tuple names (case-sensitive in C#, case-insensitive in VB), as they are either forbidden or already implicit. 例如,、 ItemN RestToStringFor instance, such as ItemN, Rest, and ToString.
    • 如果任何候选名称为重复项 (在 c # 中区分大小写,则 VB 中的) 不区分大小写,则会删除这些候选项,If any candidate names are duplicates (case-sensitive in C#, case-insensitive in VB) within the entire tuple, we drop those candidates,
  2. 在转换期间 (检查并警告从元组文本中删除名称) ,则推断出的名称不会生成任何警告。During conversions (which check and warn about dropping names from tuple literals), inferred names would not produce any warnings. 这样可以避免破坏现有的元组代码。This avoids breaking existing tuple code.

请注意,处理重复项的规则与匿名类型的规则不同。Note that the rule for handling duplicates is different than that for anonymous types. 例如,会 new { x.f1, x.f1 } 生成错误,但 (x.f1, x.f1) 仍允许 (,而不) 任何推断名称。For instance, new { x.f1, x.f1 } produces an error, but (x.f1, x.f1) would still be allowed (just without any inferred names). 这样可以避免破坏现有的元组代码。This avoids breaking existing tuple code.

为了保持一致性,相同的情况将适用于析构 ) 生成的元组 (在 c # 中为:For consistency, the same would apply to tuples produced by deconstruction-assignments (in C#):

// tuple has element names "f1" and "f2" 
var tuple = ((x.f1, x?.f2) = (1, 2));

这同样也适用于 VB 元组,使用特定于 VB 的规则从表达式推断名称,不区分大小写的名称比较。The same would also apply to VB tuples, using the VB-specific rules for inferring name from expression and case-insensitive name comparisons.

使用 c # 7.1 编译器 (或更高版本 "7.0") 时,无论该功能是否) ,都将推断元素名称 (,但会出现用于尝试访问它们的使用站点错误。When using the C# 7.1 compiler (or later) with language version "7.0", the element names will be inferred (despite the feature not being available), but there will be a use-site error for trying to access them. 这将限制稍后会出现兼容性问题 (的新代码的添加) 。This will limit additions of new code that would later face the compatibility issue (described below).

缺点Drawbacks

主要缺点是,这会引入 c # 7.0 的兼容性中断:The main drawback is that this introduces a compatibility break from C# 7.0:

Action y = () => M();
var t = (x: x, y);
t.y(); // this might have previously picked up an extension method called “y”, but would now call the lambda.

兼容性委员会发现这一中断是可接受的,因为它受到限制,而时间范围由 c # 7.0) 中的元组 (提供。The compatibility council found this break acceptable, given that it is limited and the time window since tuples shipped (in C# 7.0) is short.

参考References