c# – 为什么直接转换失败,但是在测试受限泛型类型时,“as”运算符成功?

前端之家收集整理的这篇文章主要介绍了c# – 为什么直接转换失败,但是在测试受限泛型类型时,“as”运算符成功?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
“当编译一些使用类型约束的泛型的C#代码时,我遇到了一个有趣的好奇心.我写了一个快速测试用例来说明.我在Visual Studio 2010中使用.NET 4.0.
namespace TestCast
{
    public class Fruit { }

    public class Apple : Fruit { }

    public static class Test
    {
        public static void TestFruit<FruitType>(FruitType fruit) 
            where FruitType : Fruit
        {
            if (fruit is Apple)
            {
                Apple apple = (Apple)fruit;
            }
        }
    }
}

对Apple的转换失败,并显示错误:“无法将”FruitType“类型转换为”TestCast.Apple“.但是,如果我更改行使用as操作符,它编译没有错误

Apple apple = fruit as Apple;

有人可以解释为什么会这样吗?

解决方法

我用这个问题作为 a blog article in October 2015的基础.谢谢你的伟大的问题!

Could someone please explain why this is the case?

@H_404_17@

“为什么”问题难以回答?答案是“因为这是规范说的”,那么自然的问题就是“为什么说规范呢?

所以让我让问题更加清晰:

What language design factors influenced the decision to make the given cast operator illegal on constrained type parameters?

@H_404_17@

请考虑以下情况.你有一个基本类型的水果,派生类型苹果和香蕉,现在是重要的一部分,从苹果到香蕉的用户定义的转换.

被称为M< Apple>?你认为这应该做什么?

void M<T>(T t) where T : Fruit
{
    Banana b = (Banana)t;
}

大多数阅读代码的人都会说,这应该称为从苹果到香蕉的用户定义的转换.但C#泛型不是C模板;该方法对于每个通用构造都不会从头重新编译.相反,该方法被编译一次,并且在该编译期间,为每个可能的通用实例化确定每个运算符(包括转换)的含义.

M< Apple>的身体将必须有一个用户定义的转换. M香蕉的身体将有一个身份转换. M<樱桃>会是一个错误.我们在通用方法中不能具有运算符的三个不同含义,因此运算符被拒绝.

相反,你要做的是:

void M<T>(T t) where T : Fruit
{
    Banana b = (Banana)(object)t;
}

现在这两个转换都很清楚.转换为对象是一个隐式引用转换;转换为香蕉是一个明确的参考转换.用户定义的转换从不被调用,如果这是用Cherry构建的,则错误在运行时,而不是编译时,因为它始终是从对象转换.

作为运算符不像演员运算符;它总是意味着同样的事情,无论它给出什么类型,因为as操作符从不调用用户定义的转换.因此,它可以用于一个演员是非法的上下文.

猜你在找的C#相关文章