usando tipos tipo ser referencia que instanciar genéricos genericos genericas debe colecciones clases c# generics reflection

tipos - C#: ¿Debería una clase anidada en una clase genérica considerarse genérica?



usando generics c# (4)

namespace GenericsTest { public class AGenericClass<T> { public class NestedNonGenericClass { } } }

En el ejemplo anterior, ¿debería NestedNonGenericClass considerarse una clase genérica?

La API de reflexión dice que es una clase genérica, e incluso me entrega los parámetros de la plantilla de la clase contenedora como los parámetros de la plantilla de la clase anidada.

Type nestedClass = typeof(AGenericClass<int>.NestedNonGenericClass); Console.Out.WriteLine("IsGeneric: {0}/tHasGenericArguments: {1}", nestedClass.IsGenericType, nestedClass.GetGenericArguments().Length > 0);

Esto se imprime:

IsGeneric: True HasGenericArguments: True

No estoy completamente de acuerdo con este comportamiento. Incluso si el compilador genera un tipo genérico para NestedNonGenericClass , me gustaría saber si es genérico porque fue declarado así, o porque su contenedor es genérico.

Entonces, mi pregunta es:

En primer lugar, ¿cree que está bien considerar una clase anidada genérica porque su contenedor es genérico? ¿Por qué por qué no?

En segundo lugar, ¿conoces alguna otra API que pueda ayudarme a identificar solo las clases que fueron declaradas genéricas?

PD: No pude encontrar nada relacionado con esto en las especificaciones de ECMA para genéricos (o probablemente lo pasé por alto).

--EDITAR--

Para agregar un poco más de contexto, estoy trabajando en una especie de generador de código. Y estoy usando la API de reflexión para determinar si un tipo es genérico.

Me encontré con un problema con Dictionary<TKey, TValue>.KeyCollection .

Para KeyCollection , la API de reflexión dice que es genérica y me pasa TKey y TValue que se declararon en el contenedor. Entonces, el generador termina generando Dictionary<TKey, TValue>.KeyCollection<Tkey, TValue>

La única forma en que pude resolver esto fue haciendo coincidir los parámetros de la plantilla de la clase anidada con los del contenedor y eliminando todos los que coinciden. Pero me preguntaba si hay un mejor enfoque.


En resumen, sí, un tipo hereda los argumentos de tipo de cualquier tipo que lo contenga: esta es la clave para cosas como List<T>.Enumerator y muchos otros escenarios, etc. - es fundamental que compartan el T de la clase externa (no solo cualquier T ).

La referencia ECMA es §25.1:

Cualquier clase anidada dentro de una declaración de clase genérica o una declaración de estructura genérica (§25.2) es en sí misma una declaración de clase genérica, ya que los parámetros de tipo para el tipo que lo contiene se suministrarán para crear un tipo construido.


La forma en que elijo entenderlo es que, cuando usa un tipo genérico, C # genera todo en ese tipo. Entonces, realmente, si tuviera que visualizar lo que se generaría si utilizara AGenericClass y AGenericClass en su ejemplo anterior, terminaría con dos copias de la clase anidada:

public class AGenericClass<int> { public class NestedNonGenericClass { } } public class AGenericClass<float> { public class NestedNonGenericClass { } }

Por eso, consideraría la clase anidada como una clase genérica, ya que hay dos versiones de la misma, una llamada AGenericClass <int> .NestedNonGenericClass y otra llamada AGenericClass <float> .NestedNonGenericClass. Entonces, realmente, es como si especificara explícitamente que la clase anidada también era genérica. Este comportamiento puede ser muy útil si desea que la clase anidada se adapte al tipo genérico.

Sin embargo, me resulta molesto que ya no pueda usar clases anidadas del mismo modo que hago en las clases normales. Ya no recuerdo el ejemplo exacto, lo siento, pero sé que una vez tuve que sacar una clase de un genérico para poder usarlo como estaba previsto en otros lugares del código. Iba en contra del patrón habitual que había estado usando para las clases anidadas y por eso no me gustó, pero era la única forma. Entonces puedo entender si puede estar en desacuerdo con la forma en que se hace esto, pero para ser honesto, creo que la manera en que se hace es la manera más clara. Quiero decir, es muy claro para usted y para el compilador que, si mueve la clase anidada fuera y solo la tiene como una clase normal, no desea que el compilador la genere como genérica. No creo que puedan mejorar en esto.


Sí, su clase anidada es absolutamente genérica, porque T está vinculada a un tipo (esto se conoce como genérico cerrado ) dentro del alcance de cualquier instancia de la clase anidada.

using System; using System.Collections.Generic; public class AGenericClass<T> { public class NestedNonGenericClass { public void DoSomething() { Console.WriteLine("typeof(T) == " + typeof(T)); } } } public class MyClass { public static void Main() { var c = new AGenericClass<int>.NestedNonGenericClass(); var d = new AGenericClass<DateTime>.NestedNonGenericClass(); c.DoSomething(); d.DoSomething(); Console.ReadKey(false); } }

El mismo método DoSomething() está produciendo resultados diferentes dependiendo de cómo se cerró el tipo genérico, así que sí, la clase interna definitivamente muestra un comportamiento genérico.


Si no va a utilizar T en NestedNonGenericClass, podría colocarlo fuera de la clase y hacerlo privado ... entonces no sería Genérico ...