首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GenericTypeDefinitionName来自IEnumerable<object>

GenericTypeDefinitionName来自IEnumerable<object>
EN

Stack Overflow用户
提问于 2016-07-04 10:24:47
回答 1查看 44关注 0票数 4

注意:这个问题是关于技术方面的,而不是是关于设计决策的。回答或评论不同的设计会不会是而不是回答这个问题,因为我只对这个特定问题的技术方面感兴趣。

C# 6.0中,我有一个传递IEnumerable<T>的方法

代码语言:javascript
复制
public void MyMethod(IEnumerable<object> list) { ... }

假设调用者在MyClass[]数组上调用它。

我想要的是泛型类型定义的类名,我有这个方法的实现:

代码语言:javascript
复制
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")。因此,我尝试将其重构为一个开放的泛型扩展方法,如下所示:

代码语言:javascript
复制
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(),如下所示:

代码语言:javascript
复制
public void MyMethod(IEnumerable<object> list)
{
    ...
    var name = list.GetGenericTypeDefinitionName();
    ...
}

这也很管用,但后来我意识到:‘嘿!为什么不只是return typeof(T).Name

结果,它返回字符串"Object",而我预期的结果(例如,"MyClass")与前面的实现相同。

有可能得到预期的类型吗?在处理开放的泛型类型T时,似乎所有的信息都丢失了。还有,为什么我没有得到预期的类型?C#这种特殊行为的技术细节是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-04 10:32:26

如果使用泛型方差将某些引用类型的IEnumerable<T>分配给IEnumerable<object>,则会发生您所描述的情况。

编译器将使用它知道的在编译时选择<T>,在本例中是object。但是,如果使用反射,您将得到原始名称--因为实际对象通过方差技巧保持不变。

代码语言:javascript
复制
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();
}

这是因为你实际上是在打电话

代码语言:javascript
复制
Console.WriteLine(GetByGenerics<Foo>(typed));      // Foo
Console.WriteLine(GetByGenerics<Object>(untyped)); // Object
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38182394

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档