[英]Generic type of a child class doesn't allow parents
給定這樣的結構:
class Parent { }
class Child : Parent { }
我有一個方法,該方法采用具有對象類型為Child的約束的泛型類型
static void doSomething<T>() where T : Child
{
if (typeof(T) == typeof(Parent))
{
/* ... */
}
else if (typeof(T) == typeof(Child))
{
/* ... */
}
}
唯一的問題是,如果我有:
class implementsParent : Parent { }
class implementsChild : Child { }
用一類ImplementsParent調用通用方法將不起作用:
doSomething<implementsParent>(); // compile error
doSomething<implementsChild>(); // works fine
我正在嘗試解決以下事實:重載泛型方法未考慮約束。
我在這里可以做什么?
@Sander Rijken:其他信息。
我需要使用通用類型來調用ORM框架方法,如下所示:
static void doSomething<T>() where T : Child
{
if (typeof(T) == typeof(Parent))
{
Parent obj = orm.GetObject<T>(criteria);
}
else if (typeof(T) == typeof(Child))
{
Child obj = orm.GetObject<T>(criteria);
}
}
在T處具有約束:Parent導致Child obj = orm.GetObject()中斷,因為T無法轉換為Type'Child'
@理查德·海因(Richard Hein):
最初,我有2種方法,每個方法都對子/父方法之一有約束(在這種情況下:DevExpress ORM中的XPObject和XPCustomObject-XPObject繼承自XPCustomObject)。
方法如下所示:
static void removeBlank<T>(UnitOfWork uow) where T : XPObject
{
T blank = uow.GetObjectByKey<T>(0):
if (blank != null)
{
blank.Delete();
uow.CommitChanges();
}
}
XPCustomObject(在這種情況下)用於具有short類型的PK(而不是XPObjects上的默認int)。 因此,唯一的變化是在獲取對象的調用中:
static void removeBlankCustomObject<T>(UnitOfWork uow) where T : XPCustomObject
{
T blank = uow.GetObjectByKey<T>((short)0);
if (blank != null)
{
blank.Delete();
uow.CommitChanges();
}
}
差異很小,因此我想將兩種方法合並在一起。
doSomething<implementsParent>();
之所以失敗,是因為它不符合類型約束。 T
不是從Child
派生的
您是要聲明它的意思:
static void doSomething<T>() where T : Parent
編輯:鑒於您添加的要求,這將起作用。
static void doSomething<T>() where T : Parent
{
if (typeof(T) == typeof(Parent))
{
T obj = orm.GetObject<T>(criteria);
}
else if (typeof(T) == typeof(Child))
{
T obj = orm.GetObject<T>(criteria);
}
}
除了T不是來自孩子的事實之外,我認為您還想使用
if (typeof(T).IsAssignableFrom(typeof(Parent))
...
否則,它將僅針對完全是Parent類型而不是派生類型的對象觸發。 另外,我不認為==對於Type是正確的重載。 我認為您需要使用.Equals()
注意:我可能已經倒過來了IsAssignableFrom。
您的代碼的這一部分沒有意義:
static void doSomething<T>() where T : Child
// ^^^^^^^^^^^^^^^ This says that T must be a Child,
// which necessarily means it is not
// going to be a Parent
{
if (typeof(T) == typeof(Parent)) // <-- Therefore, this will never hit
{
如果您希望能夠傳遞T : Parent
則肯定需要將約束定義為T : Parent
Parent
。
您說過,您的問題是無法將orm.GetObject<T>
的輸出orm.GetObject<T>
為Child
。 沒錯,您不能直接將其強制轉換 -但可以先將其Parent
為Parent
, 然后再 Parent
為Child
。 我認為這應該工作:
static void doSomething<T>() where T : Parent
{
if (typeof(T) == typeof(Parent))
{
Parent obj = (Parent) orm.GetObject<T>(criteria);
}
else if (typeof(T) == typeof(Child))
{
Child obj = (Child) (Parent) orm.GetObject<T>(criteria);
}
}
從編譯器的角度來看, T
就像是類層次結構的成員,有點像這樣:
┌──────────┐
| Parent |
└─┬──────┬─┘
│ │
↓ ↓
┌─────────┐ ┌───────┐
| Child | | T |
└─────────┘ └───────┘
我認為這向您說明了為什么不能直接從T
為Child
,但是可以向上轉換為Parent
(由於T
是Parent
,所以總是成功),然后向下轉換為Child
(運行時檢查它是否真的是一個Child
,當然,在您的情況下是哪個)。
(順便說一句,我假設您需要使用orm.GetObject<T>
並且不能使用orm.GetObject<Child>
。如果可以的話,這將使其更簡單,但是也許您不能,因為criteria
取決於T
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.