En un nivel alto, la inferencia del tipo de método funciona así.
En primer lugar, hacer una lista de todos los argumentos - las expresiones que usted provee - y sus correspondientes parámetro formal de tipo.
Veamos un ejemplo más interesante que el que das. Supongamos que tenemos
class Person {}
class Employee : Person {}
...
Person p = whatever;
Employee p2 = whatever;
y la misma llamada. Así hacemos las correspondencias:
p --> T1
p2 --> T1
5 --> T2
A continuación hacemos una lista de lo que "los límites" son en cada parámetro de tipo y si son "fijos". Tenemos dos parámetros de tipo, y comenzamos sin límites superiores, inferiores o exactos.
T1: (unfixed) upper { } lower { } exact { }
T2: (unfixed) upper { } lower { } exact { }
(Recordemos nuestra discusión reciente en otra pregunta acerca de los tamaños relativos de los tipos que se basan en si es o no un tipo era más o menos restrictivo; un tipo que es más restrictivo es menor que uno que es menos restrictivo. Jirafa es más pequeña que Animal porque más cosas son animales que jirafas. Los conjuntos ligados "superior" e "inferior" son exactamente eso: la solución al problema de inferencia tipo para un parámetro de tipo dado debe ser más grande o idéntica a cada límite inferior y más pequeño que o idéntico a cada límite superior, y idéntico a cada límite exacto.)
Luego vemos cada argumento y su tipo correspondiente. (Si los argumentos son lambdas, entonces deberíamos averiguar el orden en el que vemos los argumentos, pero no tiene lambdas aquí, así que ignoremos ese detalle). Para cada argumento hacemos una inferencia para el tipo de parámetro formal, y agrega los hechos que deducimos sobre esa inferencia al conjunto vinculado. Así que después de ver el primer argumento, se deduce de los límites:
T1: (unfixed) upper { } lower { Person } exact { }
T2: (unfixed) upper { } lower { } exact { }
después del segundo argumento se deduce de los límites
T1: (unfixed) upper { } lower { Person, Employee } exact { }
T2: (unfixed) upper { } lower { } exact { }
Después de que el tercer argumento se deduce de los límites:
T1: (unfixed) upper { } lower { Person, Employee } exact { }
T2: (unfixed) upper { } lower { int } exact { }
Después de que hayamos avanzado tanto como podamos, "corregimos" los límites encontrando el mejor tipo en el conjunto de límites que satisface cada límite .
Para T1, hay dos tipos en los conjuntos de límites, Person
y Employee
. ¿Hay alguno de ellos que satisfaga todos los límites establecidos? Sí. Employee
no cumple con el límite Person
porque Employee
es un tipo más pequeño que Person
; Person
es un límite inferior - significa ningún tipo más pequeño que Person
es legal. Person
satisface todos los límites: Person
es idéntico a Person
y es mayor que Employee
, por lo que cumple ambos límites. El mejor tipo en el conjunto de límites que satisface cada límite es para T1 es Person
y para T2 obviamente es int
porque solo hay un tipo en los límites establecidos para T2. Entonces arreglamos los parámetros de tipo:
T1: (fixed) Person
T2: (fixed) int
Luego preguntamos "¿tenemos un límite fijo para cada parámetro de tipo?" y la respuesta es "sí", por lo que la inferencia de tipo tiene éxito.
Si cambio el tipo del primer argumento a dynamic
, ¿cómo se deduce T1?
Si algún argumento es dinámica entonces la inferencia de T1 y T2 se difiere hasta que el tiempo de ejecución, en cuyo punto el analizador semántico considera la más derivada de tiempo de ejecución accesible tipo del valor como el tipo para el límite inferior suministrada por el argumento dinámico.
Si este tema de interés usted y desea obtener más información, hay un video de mí explicar la versión de C# 3 del algoritmo aquí:
http://blogs.msdn.com/b/ericlippert/archive/2006/11/17/a-face-made-for-email-part-three.aspx
(C# 3 no tienen límites superiores, solo límites inferiores y exactos; aparte de eso, los algoritmos son más o menos lo mismo.)
Varios artículos que he escrito sobre problemas de inferencia de tipo están aquí:
http://blogs.msdn.com/b/ericlippert/archive/tags/type+inference/
No hay 'decisión'. Se encuentra una coincidencia o se produce un error. Simplemente intente con 'MyFunc (p1," ", 5)' o 'MyFunc (" ", p2, 5)'. –