[英]Casting with generics
嘗試訪問實現類上的接口屬性時遇到問題。 問題是,我在運行時僅具有特定的(Cat)類型,因此我的應用在嘗試投射時會中斷。
這是我所擁有的:
public class Animal {}
public class Cat : Animal {}
public interface IPetSitter {}
public interface IPetSitter<T> IPetSitter where T : Animal {
T Pet { get; set; }
}
public class Kid { }
public class NeighborhoodKid : Kid, IPetSitter<Animal> {
Animal Pet { get; set; }
}
// --- Implementation ---
// Kid Timmy is instantiated elsewhere
// Animal type "A" is passed in dynamically
if (Timmy is IPetSitter) {
((IPetSitter<A>)Timmy).Pet = new A();
}
如果類型不匹配,此轉換將出錯。 我想做這樣的事情:
public interface IPetSitter {
object Pet { get; set; }
}
public interface IPetSitter<T> : IPetSitter where T : Animal {
new T Pet { get; set; }
}
// --- Implementation ---
NeighborhoodKid Timmy = new NeighborhoodKid();
((IPetSitter)Timmy).Pet = new Cat();
但這迫使實現IPetSitter的任何東西都具有[object Pet]和[Cat Pet]屬性。
我將不勝感激。 謝謝。
更新:最初我應該使它更加清楚,但是有時我將創建一個Kid
類,有時還會創建一個NeighborhoodKid
類。 這就是為什么我需要轉換為IPetSitter<T>
。 並非我創造的所有孩子都是寵物。 這開始聽起來令人毛骨悚然。
最終,蒂米被初始化為NeighbourhoodKid。 對他來說,這意味着寵物就是動物。 Timmy是IPetSitter<Animal>
,您不能將其IPetSitter<Cat>
為IPetSitter<Cat>
。
不過,假設貓:動物,您可以反過來做。
這個:
((IPetSitter<Animal>)Timmy).Pet = new Cat();
實際上只起作用是因為Timmy實際上是IPetSitter<Animal>
,因為NeighborhoodKid: IPetSitter<Animal>
,所以您實際上並沒有對該演員做任何事情-只是訪問pet屬性。
之后的問題是,沒有訪問Pet,也沒有將Cat放入其中-這是將Timmy轉換為IPetSitter<Cat>
的問題。 您正在將其貶低到並非如此。
您始終可以向上轉換,但是只能向下轉換到初始化對象所用的內容。
如果您希望NeighborhoodKid成為任何動物(包括動物本身)的IPetSitter,則應該執行以下操作:
public class NeighborhoodKid<T> : IPetSitter<T> where T : Animal
{
...
}
這樣,它是通用的,並將其限制為是動物或直接或間接源自動物的某種東西。
但是,如果將其初始化為new NeighborhoodKid<Animal>()
,則將其視為IPetSitter<Cat>
(也稱為將其轉換為IPetSitter<Cat>
,因為它已被初始化為IPetSitter<Animal>
(因為通用給NeighborhoodKid構造函數的T參數是Animal,並傳遞給IPetSitter通用參數)。
問題是您定義了
public class NeighborhoodKid : IPetSitter<Animal>
{
Animal IPetSitter<Animal>.Pet { get; set; }
}
並不是
public class NeighborhoodKid : IPetSitter<Cat>
{
Cat IPetSitter<Animal>.Pet { get; set; }
}
要么
public class NeighborhoodKid<T> : IPetSitter<T> where T : Animal
{
Cat IPetSitter<T>.Pet { get; set; }
}
為什么不只是Timmy.Pet = new Cat();
? 只需將其public
,一切就緒:
public class NeighborhoodKid : Kid, IPetSitter<Animal>
{
public Animal Pet { get; set; }
}
如果您創建一個不繼承自IPetSitter
,則該設置程序將不可用。
public class LazyNeighborhoodKid : Kid
{
// Nothing here, hes not a Pet Sitter, can access Pet
}
除了泛型在集合中的用途之外,我不是真正的泛型愛好者,這就是為什么。 您正在強迫將每個NeighborhoodKid綁定到一種特定的動物類型。 如果蒂米可以看貓或狗怎么辦? 您要為每個實例創建不同的Timmy實例嗎?
相反,我認為您是在實例級別強制使用動物類型。 例如(為簡潔起見,我將某些類型刪節了):
public interface IAnimal {...}
public class Cat : IAnimal {...}
public interface IPetSitter
{
IAnimal Pet { get; set; }
}
public class Kid : IPetSitter
{
public Kid (params Type[] allowedPets) {
_allowedPets = allowedPets;
}
readonly IEnumerable<Type> _allowedPets;
IAnimal _pet;
public IAnimal Pet
{
get {
return _pet;
}
set {
if (!_allowedPets.Contains(value.GetType()) {
throw new InvalidArgumentException("This instance does not support " + value.GetType().Name + ".");
}
_pet = value;
}
}
}
如果您將執行保留在實例級別,則不必只使用混凝土澆鑄來設置屬性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.