Ada*_*rth 19 c# compiler-errors visual-studio-2010
我有一种情况,我喜欢编译器的行为解释.给出一点代码:
interface IFoo<T>
{
T Get();
}
class FooGetter : IFoo<int>
{
public int Get()
{
return 42;
}
}
Run Code Online (Sandbox Code Playgroud)
以下编译并运行:
static class FooGetterGetter
{
public static IFoo<T> Get<T>()
{
return (IFoo<T>)new FooGetter();
}
}
Run Code Online (Sandbox Code Playgroud)
如果我们更改Foo类的签名并添加sealed关键字:
sealed class FooGetter : IFoo<int> // etc
Run Code Online (Sandbox Code Playgroud)
然后我在以下行得到编译器错误:
return (IFoo<T>)new FooGetter();
Run Code Online (Sandbox Code Playgroud)
的:
无法将类型'MyNamespace.FooGetter'转换为'MyNamespace.IFoo <T>'
有人可以解释sealed关键字的问题吗?这是针对Visual Studio 2010中的.NET 4项目的C#4.
更新:有趣的是,当我想知道为什么以下代码在sealed应用时修复它时,我偶然发现了这部分行为:
return (IFoo<T>)(IFoo<int>)new FooGetter();
Run Code Online (Sandbox Code Playgroud)
更新:只是为了澄清,当T请求的类型T与具体类型使用的类型相同时,它都运行良好.如果类型不同,则转换在运行时失败,例如:
无法将"MyNamespace.StringFoo"类型的对象强制转换为"MyNamespace.IFoo"1 [System.Int32]'
在上面的示例中,StringFoo : IFoo<string>调用者要求获取int.
因为FooGetter是一个明确的实现IFoo<int>而不是IFoo<T>一般地实现.由于它是密封的,编译器知道没有办法将它转换为泛型,IFoo<T>如果T不是一个int.如果没有密封,编译器将允许它编译并在运行时抛出异常(如果T不是)int.
如果你尝试使用除int(例如FooGetterGetter.Get<double>();)以外的任何东西,你会得到一个例外:
无法将类型为"MyNamespace.FooGetter"的对象强制转换为"MyNamespace.IFoo"1 [System.Double]'.
什么我不知道的是为什么编译器不产生非密封版本错误.怎么可能你的子类FooGetter,从而new FooGetter()给你什么实现IFoo<{something_other_than_int}>?
更新:
Per Dan Bryant和Andras Zoltan有一些方法可以从构造函数返回派生类(或者更准确地说,编译器通过分析属性返回不同的类型).所以从技术上讲,如果班级没有密封,这是可行的.