La documentación de la propiedad Type.Namespace establece:
Si el Type actual representa un tipo genérico construido, esta propiedad devuelve el espacio de nombres que contiene la definición del tipo genérico. De manera similar, si el Type actual representa un parámetro genérico T , esta propiedad devuelve el espacio de nombres que contiene la definición de tipo genérico que define T.
Si el objeto Type actual representa un parámetro genérico , esta propiedad devuelve un valor nulo.
¿Cuándo Type.Namespace devuelve nulo si la instancia representa un parámetro genérico como en el último párrafo citado? ¿O la documentación es incorrecta y las declaraciones en negrita en realidad se contradicen entre sí?
Para investigar escribí un código simple, pero no he encontrado ninguna respuesta. Todas las declaraciones de Console.WriteLine imprimen algo.
using System; namespace TypeDemo { internal static class Program { public static void Main() { var g = new G<int>(); gM(4); Console.WriteLine(typeof(G<>).Namespace); } } public class G<T> { static G() { Console.WriteLine(typeof(T).Namespace); } public G() { Console.WriteLine(typeof(T).Namespace); Console.WriteLine(GetType().Namespace); } public void M<S>(S s) { Console.WriteLine(typeof(S).Namespace); Console.WriteLine(s.GetType().Namespace); } } }Tenga en cuenta que todos los tipos que está imprimiendo no son parámetros genéricos. Observe cómo cuando se ejecutan los métodos, el tipo ya está construido. Por ejemplo, cuando haces:
var g = new G<int>(); // which calls... public G() { // T has become "int" here! Console.WriteLine(typeof(T).Namespace); Console.WriteLine(GetType().Namespace); } Para obtener un Type que represente parámetros genéricos, puede:
[llamar] al método
GetGenericArgumentsde un objetoTypeque representa una definición de tipo genérico, o al métodoGetGenericArgumentsde un objetoMethodInfoque representa una definición de método genérico.
Por ejemplo:
Console.WriteLine(typeof(Foo.C<>).GetGenericArguments()[0].Namespace); namespace Foo { class C<T> { public void Foo() { } } }y
Console.WriteLine(typeof(Foo.C).GetMethod("Foo").GetGenericArguments()[0].Namespace); namespace Foo { class C { public void Foo<T>() { } } } Ambos imprimen Foo y no he podido encontrar un caso en el que un parámetro de tipo genérico esté en un espacio de nombres, pero su espacio de Namespace devuelve nulo. Esto significa que el comportamiento real coincide con esta oración:
De manera similar, si el tipo actual representa un parámetro genérico T, esta propiedad devuelve el espacio de nombres que contiene la definición de tipo genérico que define a T.
Los documentos son contradictorios, pero correctos en principio. Type.Namespace devuelve nulo cuando el espacio de nombres no está disponible en la definición genérica. Una forma de obtener esto es MakeGenericMethodParameter:
Type t=Type.MakeGenericMethodParameter(0); Console.WriteLine("IsGenericParameter: "+t.IsGenericParameter); Console.WriteLine("Namespace: "+(t.Namespace==null?"(null)":t.Namespace));Otra es tener una implementación de tipo personalizada (es una clase abstracta de la que todos pueden derivar y anular las propiedades para hacer lo que quieran).
Editar: los documentos de Type.Namespace se corrigieron en PR https://github.com/dotnet/dotnet-api-docs/pull/7466/files