typeof 泛型和强制类型 [重复]

Posted

技术标签:

【中文标题】typeof 泛型和强制类型 [重复]【英文标题】:typeof generic and casted type [duplicate] 【发布时间】:2019-07-16 13:41:30 【问题描述】:

假设我们有通用方法:

public void GenericMethod<T>(T item)

    var typeOf = typeof(T);
    var getType = item.GetType();

我们使用以下参数调用它:

GenericMethod(1)
GenericMethod((object) 1)

结果是:

typeOf = System.Int32
getType = System.Int32

typeOf = System.Object
getType = System.Int32

谁能解释一下为什么 typeof 整数转换为对象返回 System.Object,但 .GetType() 返回 System.Int32?

【问题讨论】:

typeof takes 类型名称(您在编译时指定),GetType 获取实例的运行时类型。 另外,如果您发现自己在泛型中进行任何类型的测试,请问问自己是否为这项工作选择了正确的工具。因为这可能意味着您无法在 runtime 正常工作,而您在编译时“承诺”您可以做的事情(通过说您可以为任何类型工作,受该类型的任何泛型类型约束参数) 【参考方案1】:

typeof 返回泛型参数T静态(编译时) 类型。

GetType 返回变量item 中包含的动态(运行时) 类型。


如果您将方法设为非泛型,则更容易看出差异。假设BA 的子类型:

public void NonGenericMethod(A item)

    var typeOf = typeof(A);
    var getType = item.GetType();

在这种情况下,调用NonGenericMethod(new B()) 会产生

A
B

推荐阅读:

Run-time type vs compile-time type in C#

现在,您可能会问:为什么在您的示例中使用 NonGenericMethod(A item) 而不是 NonGenericMethod(B item) 这是一个非常好的问题!考虑以下(非通用)示例代码:

public static void NonGenericMethod(A item)

    Console.WriteLine("Method A");
    var typeOf = typeof(A);
    var getType = item.GetType();

public static void NonGenericMethod(B item)

    Console.WriteLine("Method B");
    var typeOf = typeof(B);
    var getType = item.GetType();

当您调用NonGenericMethod((A) new B()) 时会得到什么(类似于您示例中的参数(object) 1)?

Method A
A
B

为什么?因为重载决议是在编译时完成的,而不是在运行时。在编译时,表达式(A) new B() 的类型是A,就像(object) 1 的编译时类型是object

推荐阅读:

When is the generic type resolved in c#?

【讨论】:

虽然typeOf 将在第一次使用特定T 执行函数之前得到解决,但它可能会在程序开始执行之后发生。与 C++ 不同,C# 使程序可以根据输入创建无限数量的不同类型,即使不使用反射也是如此。在这种情况下,可能无法生成可以调用函数的每种类型 T 的列表,因此无法在程序执行之前确定 T 将是什么。【参考方案2】:

GenericMethod((object) 1) 中,T 将是object。 typeof 反映了这一点。

item.GetType(); 是一个虚方法,将在运行时在 Int32 上执行。

【讨论】:

【参考方案3】:

对 GetType 的调用在运行时被解析,而 typeof 在编译时被解析。 这就是为什么它给出不同的结果。 你可以在这里查看 - When and where to use GetType() or typeof()?

【讨论】:

【参考方案4】:

This Tells me Typeof 为您提供编译时间类型,而 GetType 为您提供 Exact Run time 类型。

【讨论】:

【参考方案5】:

当你忽略类型干扰时,很多事情都会变得清晰:

GenericMethod(1) 实际上是GenericMethod&lt;int&gt;(1)

GenericMethod((object) 1) 被推断为GenericMethod&lt;object&gt;((object) 1)

当您询问typeof(T) 时,它会返回您在方法调用中指定的T。您也可以使用GenericMethod&lt;object&gt;("a"),这将在typeof(T) 上返回object

GetType 返回所提供实例的实际运行时类型。

【讨论】:

以上是关于typeof 泛型和强制类型 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

C#中的泛型和泛型集合

二刷java基础第十六天——泛型和类型通配符

不明白java中的泛型和抽象类有啥区别,感觉他们作用一样啊,为啥要用2种方法呢

ch11 持有对象

关于泛型那些事?

为啥泛型类型约束不可继承/分层强制执行