uso tipos programacion inferencia c# language-features type-inference language-specifications

tipos - uso de var en c#



Problema al entender la inferencia de tipo C#como se describe en la especificación del lenguaje (1)

ACTUALIZACIÓN: Mi investigación inicial en el autobús esta mañana fue incompleta e incorrecta. El texto de la especificación de la primera fase es correcto. La implementación es correcta.

La especificación es incorrecta, ya que el orden de los eventos falla en la segunda fase. Deberíamos especificar que hacemos inferencias de tipo de salida antes de corregir los parámetros no dependientes.

Hombre, esto es complicado. He reescrito esta sección de la especificación más veces de las que puedo recordar.

He visto este problema antes, y recuerdo claramente haber realizado revisiones tales que el término incorrecto "variable de tipo" se reemplazó en todas partes con "parámetro de tipo". (Los parámetros de tipo no son ubicaciones de almacenamiento cuyo contenido puede variar, por lo que no tiene sentido llamarlos variables). Creo que al mismo tiempo noté que el orden fue incorrecto. Probablemente lo que sucedió fue que accidentalmente enviamos una versión anterior de la especificación en la web. Muchas disculpas.

Trabajaré con Mads para actualizar la especificación para que coincida con la implementación. Creo que la redacción correcta de la segunda fase debería ser algo como esto:

  • Si no existen parámetros de tipo no arreglado, la inferencia de tipo es correcta.
  • De lo contrario, si existe uno o más argumentos Ei con el tipo de parámetro correspondiente Ti, el tipo de salida de Ei con el tipo Ti contiene al menos un parámetro de tipo no fijado Xj, y ninguno de los tipos de entrada de Ei con el tipo Ti contiene ningún parámetro de tipo no fijado Xj, entonces se hace una inferencia de tipo de salida de todos estos Ei a Ti.

Ya sea que el paso anterior haya hecho o no una inferencia, ahora debemos arreglar al menos un parámetro de tipo, de la siguiente manera:

  • Si existe uno o más parámetros de tipo Xi, de modo que Xi no esté fijado, y Xi tenga un conjunto de límites no vacío, y Xi no dependa de ningún Xj, entonces cada uno de estos Xi es fijo. Si cualquier operación de reparación falla, la inferencia de tipo falla.
  • De lo contrario, si existe uno o más parámetros de tipo Xi, de modo que Xi no esté fijado, y Xi tenga un conjunto de límites no vacío, y haya al menos un parámetro de tipo Xj que dependa de Xi, entonces cada Xi de ese tipo es fijo. Si cualquier operación de reparación falla, la inferencia de tipo falla.
  • De lo contrario, no podemos avanzar y hay parámetros sin fijar. La inferencia de tipos falla.

Si la inferencia de tipos no falla ni tiene éxito, entonces se repite la segunda fase.

La idea aquí es que queremos asegurarnos de que el algoritmo nunca entre en un bucle infinito. En cada repetición de la segunda fase, o bien tiene éxito, falla o progresa. Posiblemente no puede hacer un bucle más veces que los parámetros de tipo para corregir los tipos.

Gracias por traerme esto a mi atención.

La especificación del lenguaje C # describe la inferencia de tipos en la Sección §7.5.2. Hay un detalle que no entiendo. Considere el siguiente caso:

// declaration void Method<T>(T obj, Func<string, T> func); // call Method("obj", s => (object) s);

Tanto el compilador de Microsoft como el de Mono C # infieren correctamente el object T =, pero mi comprensión del algoritmo en la especificación produciría T = string y luego fallaría. Así es como lo entiendo:

La primera etapa

  • Si Ei es una función anónima, se realiza una inferencia de tipo de parámetro explícito (§7.5.2.7) de Ei a Ti

    ⇒ no tiene efecto, porque la expresión lambda no tiene tipos de parámetros explícitos. ¿Derecha?

  • De lo contrario, si Ei tiene un tipo U y xi es un parámetro de valor, entonces se realiza una inferencia de límite inferior de U a Ti.

    ⇒ el primer parámetro es de una string tipo estático, por lo que esto agrega una string a los límites inferiores de T , ¿verdad?

La segunda fase

  • Todas las variables de tipo no fijadas Xi que no dependen de (§7.5.2.5) cualquier Xj son fijas (§7.5.2.10).

    T está sin arreglar; T no depende de nada ... así que T debería ser arreglado, ¿verdad?

§7.5.2.11 Fijación

  • El conjunto de tipos candidatos Uj comienza como el conjunto de todos los tipos en el conjunto de límites para Xi.

    ⇒ { string (límite inferior)}

  • Luego examinamos cada límite para Xi sucesivamente: [...] para cada límite inferior U de Xi, todos los tipos Uj a los que no hay una conversión implícita de U se eliminan del conjunto candidato. [...]

    ⇒ no elimina nada del conjunto de candidatos, ¿verdad?

  • Si entre los tipos candidatos restantes Uj hay un tipo único V desde el cual hay una conversión implícita a todos los otros tipos candidatos, entonces Xi se fija en V.

    ⇒ Dado que solo hay un tipo de candidato, esto es vacuamente verdadero, por lo que Xi se fija a la string . ¿Derecha?

Entonces, ¿dónde voy mal?