【问题标题】:Why can't I cast int to T, but can cast int to object and then object to T?为什么我不能将 int 转换为 T,但可以将 int 转换为 object,然后再将 object 转换为 T?
【发布时间】:2011-12-23 19:36:32
【问题描述】:

此代码无法编译:

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 result = default(T);
    if(typeof(T) == typeof(int))
    {    
        int i = 0;
        result = (T)(object)i;
    }

    return result;
}

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

【问题讨论】:

标签: c# generics casting


【解决方案1】:

正如SLaks 所说,编译器知道T 可以转换为对象,但这只是其中的一半。编译器还知道T 类型的任何对象都派生自object,因此它需要允许从object 向下转换为T。 Collections pre v2.0 需要这个。当然不是T,而是能够从对象向下转换为任何类型。除了对象之外,不可能从集合中获取任何东西。

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

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

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

【讨论】:

    【解决方案2】:

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

    相比之下,编译器确实知道T 始终可以转换为object

    例如,如果Tstring,它仍然可以转换为object,但不能转换为int

    【讨论】:

    • 那么它怎么知道 object 可以转换为 int 呢?
    • @MatthijsWessels:不是,不一定。但是编译器知道如何做到这一点:对object 执行拆箱转换,如果结果是int,则返回它,否则抛出异常。作为比较,int x = 1; long y = (long) ((object) x); 将出于相同的原因抛出。 long y = (long) x; 之所以有效,是因为(这是关键点)转换值类型意味着发生转换,而转换引用类型不会执行任何转换(在最糟糕的是,它只执行拆箱操作)。
    • 我不明白为什么它不能说:“嗯,我对 T 的了解还不够,无法进行任何特定的类型转换。不过我知道这是一个 object,所以我会像object一样进行转换。”
    • @MatthijsWessels:(long)(object)x 会抛出。 blogs.msdn.com/b/ericlippert/archive/2009/03/19/…
    • @MatthijsWessels 编译器可以做很多事情。在这种情况下。如果您比编译器了解更多,您可以告诉编译器(首先转换为对象)并且编译器不会抱怨您正在做的事情可能会导致运行时异常。另一方面,如果它只是接受它,您可能会获得更少的信息。当你编写代码时你可能没有意识到它在运行时可能不起作用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-14
    • 2020-07-03
    • 1970-01-01
    • 2022-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多