2012-10-26 123 views
5

低垂考慮下面的代碼:如何強制仿製藥

class Animal 
{ } 

class Dog : Animal 
{ } 

class Cage<T> 
{ 
    private T animal; 

    public Cage(T animal) 
    { 
     this.animal = animal; 
    } 

    public T Animal 
    { 
     get { return animal;} 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Dog dog = new Dog(); 
     Cage<Animal> animalCage = new Cage<Animal>(dog); 
     Cage<Dog> dogCage = (Cage<Dog>)animalCage; 
    } 
} 

我怎樣才能解決辦法,最後編譯器錯誤(轉換從animalCage到dogCage)?

在我的代碼我知道籠子裏有一隻狗,但我無法找到一個方法來施展它。是我創建一個轉換器並創建一個新的Cage <Dog>實例的一個例子Cage <Animal>

+0

您可能知道籠子包含一隻狗,但* type system *沒有。由於泛型參數在編譯過程中被刪除,Java泛型會讓您發出警告,但CLR泛型會保留在運行時。 –

+0

你是對的......我的問題是,如果有一個特殊的聲明(或c#關鍵字)告訴編譯器「推我」:) – user1778378

+0

沒有這樣的運氣 - 沒有辦法在運行時關閉CLR通用類型強制。 –

回答

0

您可以添加generic constraint

class Cage<T> where T : Animal 

,然後就從你的方法

public Animal Animal 
{ 
    get { return animal;} 
} 

通用約束告知編譯器,有對可提供的類型限制返回的基類對於T。如果你提供其他的東西,例如Cage<object>,您將收到編譯時錯誤。

+1

您的解決方案不能解決問題。編譯器仍然收到錯誤無法將'Cage '轉換爲'Cage ' – user1778378

2

這將工作的一般差異,除了T通常應該是協變(因爲它是一個輸出),你試圖以逆變方式使用它。此外,差異不適用於類,只適用於接口和委託,因此您需要定義一個ICage<T>

協方差會允許在其他方向施放:您可以將ICage<Dog>施放到ICage<Animal>。逆變將導致矛盾,因爲您將能夠試圖將包含CatCage<Animal>投射到Cage<Dog>,呈現get_Animal不合格。

數組是協變的,以及:你可以施放Dog[]Animal[],但你不能施放Animal[]Dog[]即使你知道它僅包含狗。

我想到的下一件事是定義一個明確的轉換運算符,但是these can't be generic

最後,你需要構建一個新的Cage<Dog>來完成這項工作。

+0

(Co)方差應用於接口,而不是類。你可能想修改你的答案來反映這一點。 –

+1

我想到了一點:無論方差限於代表和接口,他所尋找的是一個不安全的縮小演員陣容,並且允許它會導致類型系統中的矛盾。 –

4

問題1:你不能把一個Cage<Animal>實例爲Cage<Dog>實例,需要一個Cage<Dog>實例(或更具體類型的實例),其參考存儲在更少的特定類型的變量。

變化

Cage<Animal> animalCage = new Cage<Animal>(dog); 
Cage<Dog> dogCage = (Cage<Dog>)animalCage; 

Cage<Animal> animalCage = new Cage<Dog>(dog); 
Cage<Dog> dogCage = (Cage<Dog>)animalCage; 

問題2:不能存儲在Cage<Animal>變量參照Cage<Dog>實例,因爲類不支持合作/逆變。

變化

class Cage<T> 
{ 
    ... 

interface ICage<out T> 
{ 
    T Animal { get; } 
} 

class Cage<T> : ICage<T> 
{ 

Cage<Animal> animalCage = new Cage<Dog>(dog); 
Cage<Dog> dogCage = (Cage<Dog>)animalCage; 

ICage<Animal> animalCage = new Cage<Dog>(dog); 
ICage<Dog> dogCage = (Cage<Dog>)animalCage; 

然後它的工作。 (如果您不更改new Cage<Animal>new Cage<Dog>,則會在運行時發生強制性異常。)

+0

是的,這個工程,但不幸的是我不知道我可以切換到接口。 Cage對象必須通過WCF服務,並且接口在通用「對象」中解析(與KnownTypes相關的問題...)。對不起,這是一個簡化大問題的嘗試:) – user1778378

+0

我不知道我們如何提供幫助。你需要改變設計中的某些東西,但不知道更多,很難提出任何建議。 – dtb

+0

@ user1778378 KnownTypes相關的問題?您可以繼承['DataContractResolver'](http://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.datacontractresolver.aspx)以控制實際運行時類型與XML的映射。 –