密封关键字影响编译器对转换的意见 [英] Sealed keyword affects the compiler's opinion on a cast

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

问题描述

我有一种情况,我想编译器的行为解释。给定一个小代码:

  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 class FooGetter:IFoo< int> // etc 

然后我在下面一行中遇到编译错误:

  return(IFoo< T>)new FooGetter 

其中:


无法将类型MyNamespace.FooGetter转换为MyNamespace.IFoo< T>'


关于 sealed 关键字?这是在Visual Studio 2010中的.NET 4项目的C#4.



更新:有趣的是,我偶然发现了这部分行为,我想知道为什么下面的代码修复它 sealed 时应用:

  return(IFoo< T>)(IFoo< int>)new FooGetter(); 

更新:只是为了说明, T 请求与具体类型使用的 T 类型相同。如果类型不同,则转型在运行时会失败,类似于:


无法转换类型为MyNamespace.StringFoo b $ b'MyNamespace.IFoo`1 [System.Int32]'


在上面的示例中, StringFoo :IFoo< string> ,并且调用者要求获得 int

因为 FooGetter IFoo< int> 的显式实现而不是实现 IFoo< T> 。由于它是密封的,编译器知道没有办法把它转换为通用的 IFoo 如果 T 是除了 int 之外的任何东西。如果它没有被密封,编译器将允许它在运行时编译并抛出一个异常,如果 T 不是 int



如果您尝试使用 int 以外的任何东西(例如 FooGetterGetter.Get< double>(); )你会得到一个异常:


'MyNamespace.FooGetter'to type'MyNamespace.IFoo`1 [System.Double]'。


我不确定是为什么编译器不会为非密封版本生成错误。你的子类 FooGetter 如何让 new FooGetter()给你任何实现 IFoo< {something_other_than_int}>



更新


$ b b

根据 Dan Bryant Andras Zoltan 有一些方法从构造函数返回一个派生类(或者更确切地说,为了通过分析属性返回一个不同的类型)。所以技术上这是可行的,如果类是不密封。


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;
    }
}

The following compiles and runs:

static class FooGetterGetter
{
    public static IFoo<T> Get<T>()
    {
        return (IFoo<T>)new FooGetter();
    }
}

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();

Of:

Cannot convert type 'MyNamespace.FooGetter' to 'MyNamespace.IFoo<T>'

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.

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();

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:

Unable to cast object of type 'MyNamespace.StringFoo' to type 'MyNamespace.IFoo`1[System.Int32]'

In the above example, StringFoo : IFoo<string> and the caller asks to get an 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.

If you try to use it with anything other than an int (e.g. FooGetterGetter.Get<double>();) you get an exception:

Unable to cast object of type 'MyNamespace.FooGetter' to type 'MyNamespace.IFoo`1[System.Double]'.

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}>?

Update:

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.

这篇关于密封关键字影响编译器对转换的意见的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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