2013-11-23 65 views
1
error CS0029: Cannot implicitly convert type `Manager<T>' to `Manager<Asset>' 

我不明白爲什麼我得到上面的編譯時錯誤與下面的代碼。由於與管理者關聯的T類型必須來自資產,它不應該起作用嗎?泛型約束似乎不能在C#中工作

public class Manager<T> where T : Asset 
{ 
    public Manager() 
    { 
     var t = new Test(); 
     t.Manager = this; //compile-time error 
    } 
} 

public class Test 
{ 
    public Manager<Asset> Manager; 
} 

回答

1

由於與Manager關聯必須從資產中獲得的T型,不應該工作?

不,因爲通用類中的類型參數爲is not covariant。也就是說,如果您有DerivedAsset : Asset,則不允許分配Manager<Asset> manager = new Manager<DerivedAsset>()

您可以使用out T來創建類型參數協變,但這僅適用於接口。所以,你需要這樣的:

public interface IManager<out T> where T : Asset { } 

public class Test 
{ 
    public IManager<Asset> Manager; 
} 

現在你應該可以寫你的原代碼,使得Manager<T>實施IManager<T>

public class Manager<T> : IManager<T> 
    where T : Asset 
{ 
    public Manager() 
    { 
     var t = new Test(); 
     t.Manager = this;  // ok, because T in IManager<T> is covariant 
    } 
} 

(如@sjkm注意,你也可以簡單地做一投: t.Manager = (Manager<Asset>)this;但如果你確信在Manager<T>T從來都不是一個派生類這隻會工作 - 。如果Asset密封,例如)

+0

這是行不通的; '經理'不是'經理',除非'T'是'Asset' –

+0

「泛型類中的類型參數默認情況下不是協變的」:實際上,它不會是協變的,不僅僅是默認情況下。差異只適用於接口和委託,而不是類 –

+0

我試着鑄造,但我得到空 – user2800679

1

僅僅因爲一個TAsset並不意味着Manager<T>Manager<Asset>。如果Manager<T>T中共變,但它在C#中不能共變(只有接口和委託可以)。

相反,你可以Test通用還有:

public class Test<T> where T : Asset 
{ 
    public Manager<T> Manager; 
} 

和預期的一樣,現在應該工作。