C# 通用型和铸造型的类型

C# 通用型和铸造型的类型,c#,generics,C#,Generics,假设我们有通用方法: public void GenericMethod<T>(T item) { var typeOf = typeof(T); var getType = item.GetType(); } 结果是: typeOf = System.Int32 getType = System.Int32 及 有人能解释为什么强制转换到对象的整数类型返回System.object,而.GetType()返回System.Int32吗?typeof返回泛型参数T

假设我们有通用方法:

public void GenericMethod<T>(T item)
{
    var typeOf = typeof(T);
    var getType = item.GetType();
}
结果是:

typeOf = System.Int32
getType = System.Int32


有人能解释为什么强制转换到对象的整数类型返回System.object,而.GetType()返回System.Int32吗?

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

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


如果将方法设置为非泛型,则更容易看出区别。让我们假设
B
a
的一个子类型:

public void NonGenericMethod(A item)
{
    var typeOf = typeof(A);
    var getType = item.GetType();
}
在这种情况下,调用
NonGenericMethod(new B())
将产生

A
B
建议进一步阅读:


现在,您可能会问:为什么在示例中使用
NonGenericMethod(A项)
,而不是
NonGenericMethod(B项)
?这是一个很好的问题!考虑下面的(非泛型)示例代码:

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
类似)时会得到什么

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

建议进一步阅读:

通用方法((对象)1)
中,
T
将是
对象
。typeof反映了这一点


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

Typeof提供编译时类型,而GetType提供确切的运行时类型。

对GetType的调用在运行时得到解决,而Typeof在编译时得到解决。 这就是为什么它会产生不同的结果。
您可以在此处查看-

当您忽略类型干扰时,很多内容都很清楚:

GenericMethod(1)
实际上是
GenericMethod(1)

GenericMethod((对象)1)
被推断为
GenericMethod((对象)1)

当您询问
typeof(T)
时,它返回您在方法调用中指定的
T
。您还可以执行
GenericMethod(“a”)
,它将在
typeof(T)
上返回
object


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

typeof获取类型名称(您在编译时指定),
GetType
获取实例的运行时类型。此外,如果您发现自己在泛型中执行任何类型的类型测试,问问自己,你是否为这份工作选择了合适的工具。因为这可能意味着您无法在运行时正常工作—您在编译时“承诺”可以做的事情(通过说您可以为任何类型工作,受该类型参数上的任何泛型类型约束),尽管
typeOf
将在第一次使用特定
T
执行函数之前得到解决,它可能发生在程序开始执行之后。与C++不同,C语言使得程序可以根据输入创建无限数量的不同类型,甚至不用反射。在这种情况下,可能不可能生成调用函数的每种类型的
T
列表,因此不可能确定在程序执行之前是什么类型的
T
A
B
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();
}
Method A
A
B