Inferir nombres de tupla (también conocidos comoInfer tuple names (aka. inicializadores de proyección de tupla)tuple projection initializers)

ResumenSummary

En una serie de casos comunes, esta característica permite omitir los nombres de elemento de tupla y, en su lugar, deducirlos.In a number of common cases, this feature allows the tuple element names to be omitted and instead be inferred. Por ejemplo, en lugar de escribir (f1: x.f1, f2: x?.f2), los nombres de elemento "F1" y "F2" se pueden inferir de (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).

Esto es paralelo al comportamiento de los tipos anónimos, que permiten deducir los nombres de miembro durante la creación.This parallels the behavior of anonymous types, which allow inferring member names during creation. Por ejemplo, new { x.f1, y?.f2 } declara los miembros "F1" y "F2".For instance, new { x.f1, y?.f2 } declares members "f1" and "f2".

Esto es especialmente útil cuando se usan tuplas en 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); 

Diseño detalladoDetailed design

Hay dos partes del cambio:There are two parts to the change:

  1. Intente inferir un nombre de candidato para cada elemento de tupla que no tenga un nombre explícito:Try to infer a candidate name for each tuple element which does not have an explicit name:
    • Usar las mismas reglas que la inferencia de nombres para los tipos anónimos.Using same rules as name inference for anonymous types.
      • En C#, esto permite tres casos: y (identificador), x.y (acceso a miembros simple) y x?.y (acceso condicional).In C#, this allows three cases: y (identifier), x.y (simple member access) and x?.y (conditional access).
      • En VB, esto permite casos adicionales, como x.y().In VB, this allows for additional cases, such as x.y().
    • Rechazar nombres de tupla reservados (distingue mayúsculas de C#minúsculas en, sin distinción de mayúsculas y minúsculas en VB), ya que están prohibidos o ya están implícitos.Rejecting reserved tuple names (case-sensitive in C#, case-insensitive in VB), as they are either forbidden or already implicit. Por ejemplo, como ItemN, Resty ToString.For instance, such as ItemN, Rest, and ToString.
    • Si los nombres de candidatos son duplicados (con distinción de C#mayúsculas y minúsculas en, sin distinción de mayúsculas y minúsculas en VB) en toda la tupla, se quitan esos candidatos.If any candidate names are duplicates (case-sensitive in C#, case-insensitive in VB) within the entire tuple, we drop those candidates,
  2. Durante las conversiones (que comprueban y avisan sobre la eliminación de nombres de los literales de tupla), los nombres inferidos no generarán ninguna advertencia.During conversions (which check and warn about dropping names from tuple literals), inferred names would not produce any warnings. Esto evita que se interrumpa el código de tupla existente.This avoids breaking existing tuple code.

Tenga en cuenta que la regla para administrar duplicados es diferente de la de los tipos anónimos.Note that the rule for handling duplicates is different than that for anonymous types. Por ejemplo, new { x.f1, x.f1 } produce un error, pero todavía se permite el (x.f1, x.f1) (solo sin nombres inferidos).For instance, new { x.f1, x.f1 } produces an error, but (x.f1, x.f1) would still be allowed (just without any inferred names). Esto evita que se interrumpa el código de tupla existente.This avoids breaking existing tuple code.

Por coherencia, lo mismo se aplica a las tuplas generadas por las asignaciones de desconstrucción ( C#en):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));

Lo mismo se aplica también a las tuplas de VB, mediante las reglas específicas de VB para deducir el nombre de las comparaciones de expresiones y de nombres que no distinguen mayúsculas de minúsculas.The same would also apply to VB tuples, using the VB-specific rules for inferring name from expression and case-insensitive name comparisons.

Al usar el C# compilador 7,1 (o posterior) con la versión de idioma "7,0", los nombres de los elementos se deducen (a pesar de que la característica no esté disponible), pero se producirá un error de uso del sitio para intentar tener acceso a ellos.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. Esto limitará las adiciones de código nuevo que posteriormente se verán ante el problema de compatibilidad (que se describe a continuación).This will limit additions of new code that would later face the compatibility issue (described below).

DesventajasDrawbacks

La principal desventaja es que esto presenta una interrupción de compatibilidad C# de 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.

El Consejo de compatibilidad encontró este salto aceptable, dado que es limitado y el período de tiempo desde que se enviaron C# tuplas (en 7,0) es corto.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.

ReferenciasReferences