Sealed 关键字会影响编译器对演员表的看法 [英] Sealed keyword affects the compiler's opinion on a cast

查看:31
本文介绍了Sealed 关键字会影响编译器对演员表的看法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想解释编译器的行为.给出一点代码:

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.

推荐答案

因为 FooGetterIFoo 的显式实现,而不是实现 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 BryantAndras 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆