为什么在将密封类强制转换为它可能实现的接口时会出现编译错误
本文关键字:接口 实现 错误 编译 密封类 转换 为什么 | 更新日期: 2023-09-27 17:56:32
以下代码给出了编译器错误 CS0030(使用 VS 2012 的 C# 编译器编译),尽管强制转换可能会在运行时成功。删除 sealed
关键字、使用 as
强制转换或向object
添加中间转换会使错误消失。
public interface IFunny<out T> { }
public sealed class Funny<T> : IFunny<T>
{
public IFunny<TOther> Cast<TOther> ()
{
// error CS0030: Cannot convert type Funny<T>' to 'IFunny<TOther>'.
return (IFunny<TOther>) this;
}
}
在我看来,编译器仅对密封类使用启发式方法,这在通用接口实现的情况下过于严格。
它真的太严格了(在错误的意义上),还是这个错误有充分的理由?
更新:澄清我的问题:编译器无法确定编译时TOther
和T
之间是否存在关系。如果 TOther
相同或 T
的基类,则强制转换将在运行时成功,并且在所有其他情况下都会失败。无论Funny<T>
是否密封,都是如此。
C# 编译器通常不会阻止可能在运行时成功的强制转换。(例如,我可以将静态类型object
的实例强制转换为IComparable
,如果该实例没有真正实现该接口,则会导致运行时异常。为什么在这种情况下这样做sealed
?
由于它是sealed
类,因此程序员不能继承它。为了拥有强制转换对象的权限,您需要一个继承层次结构。
但是,在这种情况下,sealed
关键字保证编译器在任何情况下都不能TOther
类型T
(即它不能被继承)。因此错误。
删除 sealed
关键字是有效的,因为它创造了TOther
可能属于 T
类型的机会。因此,错误消失了。
TOther 和 T 之间没有可以在编译时确定的关系。
所以基本上你会期望IFunny<string>
投射到一个 IFunny<DataTable>
,例如,这是行不通的。