2013-12-10 36 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也驗證了我的說法,