10

以下代码给出了编译器错误 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情况下会这样做?

4

2 回答 2

4

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

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

删除sealed关键字会起作用,因为它创造了TOther可能是类型的机会T。因此错误消失了。

于 2013-01-29T08:27:32.913 回答
3

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

所以基本上你会期望转换IFunny<string>为 a IFunny<DataTable>,例如,这是行不通的。

于 2013-01-29T08:26:35.523 回答