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)。我没有深入讨论这个问题,因为问题是关于编译错误的。我起初也这么认为,但不幸的是,这不起作用(请参见编辑)。我起初也这么认为,但不幸的是,这不起作用(请参见编辑)。如果您想这样做,类型约束应该是父类或接口。但是我不太理解的部分,我认为您的示例代码中没有显示,是“重载泛型方法”,这让我觉得你真正的方法是由家长实现的…但这没有什么意义。你能提供更多关于