注意:这个问题是关于技术方面的,而不是是关于设计决策的。回答或评论不同的设计会不会是而不是回答这个问题,因为我只对这个特定问题的技术方面感兴趣。
在C# 6.0中,我有一个传递IEnumerable<T>的方法
public void MyMethod(IEnumerable<object> list) { ... }假设调用者在MyClass[]数组上调用它。
我想要的是泛型类型定义的类名,我有这个方法的实现:
public void MyMethod(IEnumerable<object> list)
{
...
var name =
from abstraction in list.GetType().GetInterfaces()
where abstraction.IsGenericType
&& abstraction.GetGenericTypeDefinition() == typeof(IEnumerable<>)
from genericArgumentType in abstraction.GetGenericArguments()
select genericArgumentType.Name;
...
}现在在这种情况下(在方法的主体内),它正确地返回类的名称(例如,字符串"MyClass")。因此,我尝试将其重构为一个开放的泛型扩展方法,如下所示:
public static string GetGenericTypeDefinitionName<T>(this IEnumerable<T> list)
{
var name =
from abstraction in list.GetType().GetInterfaces()
where abstraction.IsGenericType
&& abstraction.GetGenericTypeDefinition() == typeof(IEnumerable<>)
from genericArgumentType in abstraction.GetGenericArguments()
select genericArgumentType.Name;
return name.Single();
}然后从GetGenericTypeDefinitionName()内部调用MyMethod(),如下所示:
public void MyMethod(IEnumerable<object> list)
{
...
var name = list.GetGenericTypeDefinitionName();
...
}这也很管用,但后来我意识到:‘嘿!为什么不只是return typeof(T).Name‘
结果,它返回字符串"Object",而我预期的结果(例如,"MyClass")与前面的实现相同。
有可能得到预期的类型吗?在处理开放的泛型类型T时,似乎所有的信息都丢失了。还有,为什么我没有得到预期的类型?C#这种特殊行为的技术细节是什么?
发布于 2016-07-04 10:32:26
如果使用泛型方差将某些引用类型的IEnumerable<T>分配给IEnumerable<object>,则会发生您所描述的情况。
编译器将使用它知道的在编译时选择<T>,在本例中是object。但是,如果使用反射,您将得到原始名称--因为实际对象通过方差技巧保持不变。
static void Main()
{
IEnumerable<Foo> typed = new Foo[0];
IEnumerable<object> untyped = typed;
Console.WriteLine(typed.GetByGenerics()); // Foo
Console.WriteLine(untyped.GetByGenerics()); // Object
Console.WriteLine(typed.GetByReflection()); // Foo
Console.WriteLine(untyped.GetByReflection()); // Foo
}
public static string GetByGenerics<T>(this IEnumerable<T> list)
{
return typeof(T).Name;
}
public static string GetByReflection<T>(this IEnumerable<T> list)
{
var name =
from abstraction in list.GetType().GetInterfaces()
where abstraction.IsGenericType
&& abstraction.GetGenericTypeDefinition() == typeof(IEnumerable<>)
from genericArgumentType in abstraction.GetGenericArguments()
select genericArgumentType.Name;
return name.Single();
}这是因为你实际上是在打电话
Console.WriteLine(GetByGenerics<Foo>(typed)); // Foo
Console.WriteLine(GetByGenerics<Object>(untyped)); // Objecthttps://stackoverflow.com/questions/38182394
复制相似问题