2015-10-09 75 views
4

假設我有以下的接口和實現它的類:爲什麼我不能將對象轉換爲受約束的泛型?

public interface IAnimal 
{ 
    void Feed(); 
} 

public class Animal : IAnimal 
{ 
    public void Feed() 
    { 
     // feed 
    } 
} 

爲什麼不能從我的具體類轉換爲一個通用的約束爲IAnimal,當我的動物類實現呢?

public class Zoo 
{ 
    private readonly Animal animal = new Animal(); 

    public TAnimal GetAnimal<TAnimal>() where TAnimal : IAnimal 
    { 
     return (TAnimal)(this.animal); // This will not compile 
    } 
} 

如果我改變動物的字段類型是IAnimal而不是動物,然後它編譯OK:

public class Zoo 
{ 
    private readonly IAnimal animal = new Animal(); 

    public TAnimal GetAnimal<TAnimal>() where TAnimal : IAnimal 
    { 
     return (TAnimal)(this.animal); // this compiles 
    } 
} 

或者,或者,如果我投給通用TAnimal之前做了一個顯式的IAnimal那麼這也將編譯罰款:

public class Zoo 
{ 
    private readonly Animal animal = new Animal(); 

    public TAnimal GetAnimal<TAnimal>() where TAnimal : IAnimal 
    { 
     return (TAnimal)((IAnimal)this.animal); // this compiles 
    } 
} 

所以我的問題是 - 爲什麼不第一個版本的工作?當然,編譯器有足夠的信息來知道Animal實現了IAnimal,所以考慮到這個限制,將它轉換爲TAnimal是有效的?還是有什麼我在這裏失蹤?從IAnimalTAnimal

+1

而且當你告訴泛型使用Animal2時,代碼將會崩潰,因爲動物不能投入到Animal2中。不知道這是否是原因,但可以。即使它是IAnimal並且對象本身是Animal,它仍然會崩潰。 –

+4

如果'TAnimal'是一種類型:'Human',實現'IAnimal'但是不能從'Animal' ...中獲得?那麼演員陣容就是'Animal' - >'Human',所以編譯器不允許你演員演員。 – pwas

+0

'在哪裏TAnimal:IAnimal'這是問題。讓它'在哪裏TAnimal:Animal' –

回答

4

Animal繼承不從Animal繼承,而是來自IAnimal了。你不能投從AB如果B不從A繼承,這將是這樣的:

DataTable dt = new DataTable(); 
string str = (string)dt; 

您不能從object做到這一點,即使DataTablestring繼承。到沒有繼承關係,你必須定義類型之間的轉換conversion operators

+0

@ M.kazemAkhgary謝謝,我糾正了,我的英語很差:) –

1

假設你也是一個Dog類:

public class Dog : IAnimal 
{ 

} 

如果你調用你的方法:用DogGetAnimal<TAnimal>()TAnimal,你將有一個這樣的代碼:

public class Zoo 
{ 
    private readonly Animal animal = new Animal(); 

    public Dog GetAnimal() 
    { 
     return (Dog)this.animal; 
    } 
} 

當然Dog不會從Animal繼承這樣的鑄造是錯誤的。

然後你有你的第二個例子:

public class Zoo 
{ 
    private readonly IAnimal animal = new Animal(); 

    public Dog GetAnimal() 
    { 
     return (Dog)this.animal; 
    } 
} 

Dog正在實施IAnimal,因此這將編譯。它會在運行時拋出一個InvalidCastException。同樣的道理也適用於雙鑄件在第三個例子:

public class Zoo 
{ 
    private readonly Animal animal = new Animal(); 

    public Dog GetAnimal() 
    { 
     return (Dog)(IAnimal)this.animal; 
    } 
} 

你可以施放從AnimalIAnimalIAnimalDog,但它會拋出InvalidCastException

相關問題