我有一种情况想要解释编译器的行为。给出一些代码:
interface IFoo<T>
{
T Get();
}
class FooGetter : IFoo<int>
{
public int Get()
{
return 42;
}
}
以下编译并运行:
static class FooGetterGetter
{
public static IFoo<T> Get<T>()
{
return (IFoo<T>)new FooGetter();
}
}
如果我们更改 Foo
的签名类并添加 sealed
关键词:
sealed class FooGetter : IFoo<int> // etc
然后我在以下行中收到编译器错误:
return (IFoo<T>)new FooGetter();
属于:
Cannot convert type 'MyNamespace.FooGetter' to 'MyNamespace.IFoo<T>'
有人可以解释这里发生的关于 sealed
的事情吗?关键词?这是针对 Visual Studio 2010 中的 .NET 4 项目的 C# 4。
更新:有趣的是,当我想知道为什么以下代码在 sealed
时修复它时,我偶然发现了这部分行为。被应用:
return (IFoo<T>)(IFoo<int>)new FooGetter();
更新: 只是为了澄清,当类型为 T
时一切正常requested 与 T
的类型相同由具体类型使用。如果类型不同,则转换在运行时会失败,例如:
Unable to cast object of type 'MyNamespace.StringFoo' to type 'MyNamespace.IFoo`1[System.Int32]'
在上面的例子中,StringFoo : IFoo<string>
来电者要求获得 int
.
最佳答案
因为 FooGetter
是 IFoo<int>
的显式实现而不是实现 IFoo<T>
一般地。由于它是密封的,编译器知道无法将其转换为通用的 IFoo<T>
。如果T
是 int
以外的任何东西.如果它没有被密封,编译器将允许它编译并在运行时抛出异常如果 T
不是 int
.
如果您尝试将它与 int
以外的任何东西一起使用(例如 FooGetterGetter.Get<double>();
)你得到一个异常(exception):
Unable to cast object of type 'MyNamespace.FooGetter' to type 'MyNamespace.IFoo`1[System.Double]'.
我不确定为什么编译器不会为非密封版本生成错误。你的子类怎么会FooGetter
这样 new FooGetter()
给你任何实现 IFoo<{something_other_than_int}>
的东西?
更新:
根据 Dan Bryant和 Andras Zoltan有一些方法可以从构造函数返回派生类(或者更准确地说,编译器可以通过分析属性返回不同的类型)。所以从技术上讲,如果类不是密封的,这是可行的。
关于c# - sealed 关键字会影响编译器对强制转换的看法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8912542/