2013-12-10 35 views
1

考虑以下C#泛型古怪

public class MyBuilder {} 

public interface IBuilder 
{ 
    MyBuilder Builder { get; } 
} 

public class TestGeneric<B, S> where B : IBuilder, new()where S : MyBuilder 
{ 
    public TestGeneric() 
    { 
     B b = new B(); 
     S s = b.Builder ;// as S; 
    } 
} 

编译器会抱怨:

无法隐式转换类型 'MyBuilder' 到 'S'。存在明确的 转换...

为什么不呢? 毕竟我明确指出S:MyBuilder,这是一个base类。

我也不认为Parameter Invariance适用于此。 和this SO问题是相似的,但我没有看到为什么答案。 我使用VS 2013和.Net 4.5。当然还有铸造作品。

编辑:我有一个密封的类以前。

回答

2

毕竟我写明S : MyBuilder,这是一个基类。

是的,但你想向上转型MyBuilderS这是行不通的,除非SMyBuilder

TestGeneric<IBuilderImpl,MyNewBuilder> g;  

会尝试投MyBuilderMyNewBuilder这将在运行时失败。

+0

但是不是S:MyBuilder和'is-a'的关系?编译器不应该尝试在这里上传。如果MyNewBuilder:MyBuilder你的例子应该工作得很好。 – narendra

+0

@narendra但是'IBuilder.Builder'是'MyBuilder'(不一定是'S'),所以's s = b.Builder'会将'MyBuilder'上传到'S'。 –

+0

啊! IBuilder.MyBuilder不是MyBuilder,因此会产生upcast。谢谢! – narendra

2

你应该得到一个下面的错误

CS0701: 'System.Text.StringBuilder' 不是一个有效的约束。用作约束的类型必须是接口,非密封类或类型参数。

+0

我有previously.sry – narendra

+0

我猜密封类该错误将在_无效转换被修复后出现。 –

+0

正确 - 我修正了 – narendra

0

我并不完全相信,所以我继续挖掘和骚扰同事! 答案如下:from MSFT

For reference types, an explicit cast is required if you need to convert from a base type to a derived type

在这里是精确的情况下,和我的同事亚历克斯指出:

S inherits from MyBuilder, is not the same as "S.GetType() == typeof(MyBuilder)"

SO question也验证了我的说法,