簡體   English   中英

子類別的通用類型不允許父母

[英]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 沒錯,您不能直接將其強制轉換 -但可以先將ParentParent然后再 ParentChild 我認為這應該工作:

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   |
            └─────────┘  └───────┘

我認為這向您說明了為什么不能直接從TChild ,但是可以向上轉換為Parent (由於TParent ,所以總是成功),然后向下轉換為Child (運行時檢查它是否真的一個Child ,當然,在您的情況下是哪個)。

(順便說一句,我假設您需要使用orm.GetObject<T>並且不能使用orm.GetObject<Child> 。如果可以的話,這將使其更簡單,但是也許您不能,因為criteria取決於T

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM