C# 子类的泛型类型不为';不允许父母

C# 子类的泛型类型不为';不允许父母,c#,generics,overloading,C#,Generics,Overloading,考虑到这样的结构: class Parent { } class Child : Parent { } ┌──────────┐ | Parent | └─┬──────┬─┘ │ │ ↓ ↓ ┌─────────┐ ┌───────┐

考虑到这样的结构:

class Parent { }

class Child : Parent { }
                  ┌──────────┐
                  |  Parent  |
                  └─┬──────┬─┘
                    │      │
                    ↓      ↓
            ┌─────────┐  ┌───────┐
            |  Child  |  |   T   |
            └─────────┘  └───────┘
我有一个方法,它接受一个泛型类型,并带有一个约束,即对象的类型是Child

static void doSomething<T>() where T : Child
{
    if (typeof(T) == typeof(Parent))
    {
        /* ... */
    }
    else if (typeof(T) == typeof(Child))
    {
        /* ... */
    }
}
使用ImplementsAgent类型调用泛型方法将不起作用:

doSomething<implementsParent>(); // compile error
doSomething<implementsChild>(); // works fine
doSomething();//编译错误
doSomething();//很好
我试图绕过这样一个事实:重载泛型方法时不考虑约束

我能在这里做什么

@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);
    }
}
static void doSomething(),其中T:Child
{
if(typeof(T)=typeof(父级))
{
父对象=orm.GetObject(标准);
}
else if(typeof(T)=typeof(Child))
{
子对象=orm.GetObject(标准);
}
}
使约束位于T:Parent的位置会导致子对象obj=orm.GetObject()中断,因为T无法转换为“Child”类型

@理查德·海因:

最初,我有两个方法,每个方法都有一个对子/父对象的约束(在本例中:来自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();
    }
}
静态void removeBlank(UnitOfWork uow),其中T:XPObject
{
T blank=uow.GetObjectByKey(0):
if(空白!=null)
{
空白。删除();
uow.CommitChanges();
}
}
XPCustomObject用于(在本例中)具有short类型的PKs(而不是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();
    }
}
静态void removeBlankCustomObject(UnitOfWork uow),其中T:XPCustomObject
{
T blank=uow.GetObjectByKey((短)0);
if(空白!=null)
{
空白。删除();
uow.CommitChanges();
}
}
差别很小,所以我想把这两种方法合并在一起

doSomething<implementsParent>();
编辑:根据您添加的要求,这将起作用

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);
    }
}
static void doSomething(),其中T:Parent
{
if(typeof(T)=typeof(父级))
{
T obj=orm.GetObject(标准);
}
else if(typeof(T)=typeof(Child))
{
T obj=orm.GetObject(标准);
}
}
编辑:根据您添加的要求,这将起作用

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);
    }
}
static void doSomething(),其中T:Parent
{
if(typeof(T)=typeof(父级))
{
T obj=orm.GetObject(标准);
}
else if(typeof(T)=typeof(Child))
{
T obj=orm.GetObject(标准);
}
}

除了T不是从child派生的事实之外,我认为您应该使用

if (typeof(T).IsAssignableFrom(typeof(Parent))
  ...
否则,它将只针对与父类型完全相同的对象触发,而不是派生类型。另外,我不认为==对于类型是正确重载的。我认为您需要使用.Equals()


注意:我可能从后面得到了IsAssignable

除了T不是源于child之外,我认为您应该使用

if (typeof(T).IsAssignableFrom(typeof(Parent))
  ...
否则,它将只针对与父类型完全相同的对象触发,而不是派生类型。另外,我不认为==对于类型是正确重载的。我认为您需要使用.Equals()


注意:我可能从后面得到了IsAssignable

这部分代码没有意义:

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
就像类层次结构的一个成员,有点像这样:

class Parent { }

class Child : Parent { }
                  ┌──────────┐
                  |  Parent  |
                  └─┬──────┬─┘
                    │      │
                    ↓      ↓
            ┌─────────┐  ┌───────┐
            |  Child  |  |   T   |
            └─────────┘  └───────┘
我想这说明了为什么你不能直接从
t
转换到
Child
,但是你可以向上转换到
Parent
(这总是成功的,因为
t
Parent
),然后向下转换到
Child
(运行时会检查它是否真的是
子对象,当然在您的情况下,它会是)


(顺便说一下,我假设您需要使用
orm.GetObject
,而不能使用
orm.GetObject
。如果可以,这会使它更简单,但可能您不能,因为
标准
取决于
t

这部分代码没有意义:

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
就像类层次结构的一个成员,有点像这样:

class Parent { }

class Child : Parent { }
                  ┌──────────┐
                  |  Parent  |
                  └─┬──────┬─┘
                    │      │
                    ↓      ↓
            ┌─────────┐  ┌───────┐
            |  Child  |  |   T   |
            └─────────┘  └───────┘
我想这说明了为什么你不能直接从
t
转换到
Child
,但是你可以向上转换到
Parent
(这总是成功的,因为
t
Parent
),然后向下转换到
Child
(运行时会检查它是否真的是
子对象,当然在您的情况下,它会是)


(顺便说一句,我假设您需要使用
orm.GetObject
,而不能使用
orm.GetObject
。如果可以,这将使它更简单,但可能您不能,因为
标准取决于
t

您可以安全地使用==来比较类型,但您是对的。需要检查IsAssignableFrom。但是,您颠倒了参数,需要是
typeof(Parent)。IsAssignableFrom(typeof(T))
(您想知道T是否可以分配给Parent)。我没有深入讨论这个问题,因为问题是关于编译错误。您可以安全地使用==来比较类型,但您是对的。需要检查IsAssignableFrom。但是,您反转了参数,需要是
typeof(Parent)。IsAssignableFrom(typeof(t))
(您想知道是否可以将t分配给Parent)。我没有深入讨论这个问题,因为问题是关于编译错误的。我起初也这么认为,但不幸的是,这不起作用(请参见编辑)。我起初也这么认为,但不幸的是,这不起作用(请参见编辑)。如果您想这样做,类型约束应该是父类或接口。但是我不太理解的部分,我认为您的示例代码中没有显示,是“重载泛型方法”,这让我觉得你真正的方法是由家长实现的…但这没有什么意义。你能提供更多关于