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的基础.谢谢你的伟大的问题!
“为什么”问题难以回答?答案是“因为这是规范说的”,那么自然的问题就是“为什么说规范呢? 所以让我让问题更加清晰:
请考虑以下情况.你有一个基本类型的水果,派生类型苹果和香蕉,现在是重要的一部分,从苹果到香蕉的用户定义的转换. 被称为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操作符从不调用用户定义的转换.因此,它可以用于一个演员是非法的上下文. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |