Sealed 关键字会影响编译器对演员表的看法 [英] Sealed keyword affects the compiler's opinion on a cast
问题描述
我想解释编译器的行为.给出一点代码:
I have a situation where I'd like the behaviour of the compiler explained. Given a little code:
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
关键字:
If we make a change to the signature of the Foo
class and add the sealed
keyword:
sealed class FooGetter : IFoo<int> // etc
然后我在以下行收到编译器错误:
Then I get a compiler error on the following line:
return (IFoo<T>)new FooGetter();
来自:
无法将类型MyNamespace.FooGetter"转换为MyNamespace.IFoo
Cannot convert type 'MyNamespace.FooGetter' to 'MyNamespace.IFoo<T>'
有人可以解释一下关于 sealed
关键字的情况吗?这是针对 Visual Studio 2010 中的 .NET 4 项目的 C# 4.
Can someone explain what is happening here with regards to the sealed
keyword? This is C# 4 against a .NET 4 project in Visual Studio 2010.
更新:有趣的是,当我想知道为什么在应用 sealed
时以下代码修复它时,我偶然发现了行为的那部分:
Update: interestingly enough I stumbled on that part of the behaviour when I was wondering why the following code fixes it when sealed
is applied:
return (IFoo<T>)(IFoo<int>)new FooGetter();
更新: 只是为了澄清,当请求的 T
的类型与使用的 T
的类型相同时,一切运行正常具体类型.如果类型不同,则转换在运行时会失败,类似于:
Update: just for clarification, it all runs fine when the type of T
requested is the same as the type of T
used by the concrete type. If the types differ, the cast fails at runtime with something like:
无法将类型为MyNamespace.StringFoo"的对象转换为类型'MyNamespace.IFoo`1[System.Int32]'
Unable to cast object of type 'MyNamespace.StringFoo' to type 'MyNamespace.IFoo`1[System.Int32]'
在上面的例子中,StringFoo : IFoo
并且调用者要求得到一个 int
.
In the above example, StringFoo : IFoo<string>
and the caller asks to get an int
.
推荐答案
因为 FooGetter
是 IFoo
的显式实现,而不是实现 IFoo<;T>
一般而言.由于它是密封的,编译器知道如果 T
不是 int
.如果它没有被密封,如果 T
不是 int
,编译器将允许它编译并在运行时抛出异常.
Because FooGetter
is an explicit implementation of IFoo<int>
instead of implementing IFoo<T>
generically. Since it is sealed, the compiler knows there's no way to cast it to a generic IFoo<T>
if T
is anything other than an int
. If it were not sealed, the compiler would allow it to compile and throw an exception at runtime if T
was not an int
.
如果你尝试将它与 int
以外的任何东西一起使用(例如 FooGetterGetter.Get
),你会得到一个异常:
If you try to use it with anything other than an int
(e.g. FooGetterGetter.Get<double>();
) you get an exception:
无法将MyNamespace.FooGetter"类型的对象转换为MyNamespace.IFoo`1[System.Double]".
Unable to cast object of type 'MyNamespace.FooGetter' to type 'MyNamespace.IFoo`1[System.Double]'.
我不确定的是为什么编译器不会不为非密封版本生成错误.你的子类 FooGetter
如何让 new FooGetter()
给你任何实现 IFoo<{something_other_than_int}>
的东西?
What I'm not sure of is why the compiler does not generate an error for the non-sealed version. How could your sub-class FooGetter
such that new FooGetter()
give you anything that implements IFoo<{something_other_than_int}>
?
更新:
根据 Dan Bryant 和 Andras Zoltan 有一些方法可以从构造函数返回派生类(或者更准确地说,编译器通过分析属性返回不同的类型).所以从技术上讲,如果类不是密封的,这是可行的.
Per Dan Bryant and Andras Zoltan there are methods to return a derived class from a constructor (or possibly more precisely for the compiler to return a different type by analyzing attributes). So technically this is feasible if the class is not sealed.
这篇关于Sealed 关键字会影响编译器对演员表的看法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!