C# 为什么可以';我将int转换为t,但可以将int转换为object,然后将object转换为t吗?

C# 为什么可以';我将int转换为t,但可以将int转换为object,然后将object转换为t吗?,c#,generics,casting,C#,Generics,Casting,此代码不编译: public T Get<T>() { T result = default(T); if(typeof(T) == typeof(int)) { int i = 0; result = (T)i; } return result; } public T Get() { T结果=默认值(T); if(typeof(T)=typeof(int)) { int i=0; 结果=(T

此代码不编译:

public T Get<T>()
{
    T result = default(T);
    if(typeof(T) == typeof(int))
    {    
        int i = 0;
        result = (T)i;
    }

    return result;
}
public T Get()
{
T结果=默认值(T);
if(typeof(T)=typeof(int))
{    
int i=0;
结果=(T)i;
}
返回结果;
}
但是,此代码不编译:

public T Get<T>()
{
    T result = default(T);
    if(typeof(T) == typeof(int))
    {    
        int i = 0;
        result = (T)(object)i;
    }

    return result;
}
public T Get()
{
T结果=默认值(T);
if(typeof(T)=typeof(int))
{    
int i=0;
结果=(T)(对象)i;
}
返回结果;
}

代码也可以正常工作。我不明白为什么编译器可以将一个对象(实际类型可以是任何类型)强制转换为t,但不能将int(从对象继承)强制转换为t。

编译器不知道
t
int
。(即使您刚刚证明在您的
if
中它是
int

相比之下,编译器知道
T
总是可转换为
对象

例如,如果
T
string
,它仍然可以转换为
object
,但不能转换为
int
,,正如所说的,编译器知道
T
可以转换为object,但这只是它的一半。编译器还知道
T
类型的任何对象都是从
object
派生的,因此它需要允许从
object
向下转换到
T
。v2.0之前的集合需要这样做。当然不是为了
T
,而是为了能够从对象向下转换到任何类型。除了对象之外,不可能从集合中获得任何东西

当谈论
T
int
时,情况并非如此。当然,由于if语句,您的代码在运行时不会出现这些问题,但是编译器看不到这一点。一般来说(不是在这种情况下),证明在某些外部条件为真的情况下,你永远不会到达if的主体是,因为我们希望编译器在某一点上完成,它不会尝试基本上解决一个问题

在许多情况下,在非泛型代码中不允许用特定类型替换
T


如果您不能将代码编写为非泛型,以使用特定类型替换
t
,那么它不仅在本例中有效,而且在一般情况下无效。如果您知道,对于该方法的所有用例,它实际上都是有效的,那么您可以使用通用方法。

您能看到int i是int和(T)(对象)类型的区别吗我想你们可能想看看什么是装箱和拆箱隐式强制转换与显式强制转换,这看起来像是一个可能的重复,所以它怎么知道对象可以转换为int?@MatthijsWessels:不,不一定。但是编译器知道如何做:对
对象执行取消装箱转换,如果结果是
int
,则返回该值,否则抛出异常。为了进行比较,
intx=1;长y=(长)((对象)x)将基于相同的原因抛出<代码>长y=(长)x只起作用,因为(这是关键点)强制转换值类型意味着发生转换,而强制转换引用类型不执行任何转换(最坏情况下,它只执行取消装箱操作)。我不明白为什么它不能说:“嗯,我对
t
了解不够,无法进行任何特定的类型转换。虽然我知道它是一个
对象
,所以我会像它是一个
对象一样进行转换。@MatthijsWessels:
(long)(object)x
会抛出。@MatthijsWessels编译器可以做很多事情。在这种情况下。如果你知道的比编译器多,你可以告诉编译器(先向对象强制转换)而且编译器不会抱怨您所做的操作可能会导致运行时异常。另一方面,如果它只是接受它,您可能会获得较少的信息。您可能在编写代码时没有意识到它可能在运行时不起作用