将密封类转换为可能实现的接口时,为什么会出现编译错误?

时间:2013-01-29 08:20:01

标签: c# generics compiler-errors

以下代码给出了编译器错误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;
    }
  }

在我看来,编译器只使用密码类的启发式算法,在通用接口实现的情况下过于严格。

它是否真的过于严格(从错误的意义上说),还是有充分的理由发生此错误?

更新:澄清我的问题:编译器无法确定编译时TOtherT之间是否存在关联。如果TOtherT相同或基类Funny<T>,则转换将在运行时成功,并且在所有其他情况下都会失败。无论object是否被密封,都是如此。

C#编译器通常不会阻止在运行时可能成功的强制转换。 (例如,我可以将静态类型IComparable的实例强制转换为sealed,如果实例没有真正实现该接口,则会导致运行时异常。)为什么会在此{{1}中执行此操作case?

2 个答案:

答案 0 :(得分:4)

由于它是sealed类,因此程序员不能继承它。并且为了拥有转换对象的权限,您需要一个继承层次结构。

但是,在这种情况下,sealed关键字保证编译器TOther在任何情况下都不能是T类型(即它不能被继承)。因此错误。

删除sealed关键字有效,因为它可以创建TOther类型为T的机会。因此错误消失了。

答案 1 :(得分:3)

TOther和T之间没有关系可以在编译时确定。

所以基本上你会期望将IFunny<string>投射到IFunny<DataTable>,例如,这不会起作用。