variable usar type como check and c# generics typeof type-parameter

c# - usar - typeof(T) dentro de los tipos genéricos anidados



gettype() and typeof (3)

No entiendo por qué lo siguiente se comporta como lo hace en absoluto. Ni siquiera sé si es por esconderse o algo más.

class A<T> { public class B : A<int> { public void b() { Console.WriteLine(typeof(T).ToString()); } public class C : B { public void c() { Console.WriteLine(typeof(T).ToString()); } } public class D : A<T>.B { public void d() { Console.WriteLine(typeof(T).ToString()); } } } } class Program { static void Main(string[] args) { A<string>.B.C c = new A<string>.B.C(); A<string>.B.D d = new A<string>.B.D(); c.c(); c.b(); d.d(); d.b(); } }

Las preguntas son:

  1. ¿Por qué cc() produce System.String mientras que cb() produce System.Int32 ?

  2. ¿Por qué dd() y db() producen System.String y no se comportan exactamente de la misma manera que la clase C ?


Esta es una variación de un rompecabezas que publiqué en mi blog hace muchos años:

blogs.msdn.com/b/ericlippert/archive/2007/07/27/…

y Cyrus publicó en su blog antes de eso:

http://blogs.msdn.com/b/cyrusn/archive/2005/08/01/446431.aspx

Vea la discusión allí para más detalles.

Brevemente: ¿qué significa B en la class C : B ? Revise el contenedor, class B ¿Contiene algún tipo llamado B ? No. Entonces revisa la clase base del contenedor. La clase base del contenedor es A<int> . ¿Contiene algo llamado B ? Sí. Entonces esto significa class C : A<int>.B .

Ahora decimos que c es A<string>.BC . Llamamos al método A<string>.BCc() ¿Qué es T largo de A<string> ? Obviamente la string . Entonces cc() imprime String para T

Ahora llamamos A<string>.BCb() pero no hay tal método en A<string>.BC directamente. ¿De dónde saca este método? Desde su clase base. ¿Cuál es su clase base? A<int>.B . Entonces llamamos A<int>.Bb() . ¿Qué es T largo de A<int> ? Obviamente int .

Ahora llegamos a A<string>.BDd() . La clase base es irrelevante. T es string largo de A<string> .

Y finalmente A<string>.BDb() . No hay tal método en A<string>.BD directamente, por lo que debe obtenerlo de su tipo base. T es una string en A<string> , por lo que el tipo base es A<string>.B . Por lo tanto, esto llama A<string>.Bb() .

Si eso no tiene sentido para ti, explica todo. Vamos a sustituir String por T:

class A_string { public class B : A_int { public void b() { Console.WriteLine(typeof(string).ToString()); } public class C : A_int.B // Note! { public void c() { Console.WriteLine(typeof(string).ToString()); } } public class D : A_string.B { public void d() { Console.WriteLine(typeof(string).ToString()); } } } }

OK, ese es uno de los tipos. Ahora hagamos lo mismo para int:

class A_int { public class B : A_int { public void b() { Console.WriteLine(typeof(int).ToString()); } public class C : A_int.B // Note! { public void c() { Console.WriteLine(typeof(int).ToString()); } } public class D : A_int.B { public void d() { Console.WriteLine(typeof(int).ToString()); } } } }

Ahora, dados esos tipos, debería estar claro qué A_string.BCc() , A_string.BCb() , etc., todos imprimen.


Este es un ejemplo un poco más complejo de un rompecabezas que Eric Lippert describe en blogs.msdn.com/b/ericlippert/archive/2007/07/27/… , que luego se explica en este artículo .

El breve resumen (recomiendo leer el artículo) es que en este caso hay una ambigüedad en la línea C : B Se debe tomar una decisión sobre lo que B realmente significa en este contexto; ya sea A<T>.B o A<int>.B . Esencialmente, el compilador elige este último, dado un criterio particular de "betterness" descrito en la especificación.


A<string>.BC hereda A<int>.B , porque B en la declaración de la clase base proviene primero del ámbito primario interno. (para aclarar, su ámbito principal es A<T>.B , que contiene un tipo llamado B refiere a A<int>.B , heredado de su clase base A<int> )

La llamada b() proviene de su clase base, en la que T (del ámbito principal) es int .

D explícitamente hereda A<T>.B , usando T desde el alcance más externo ( A<T> ), por lo que su T siempre proviene de A<> en su nombre de tipo.