给出这样的结构:
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:
最初,我有两个方法,每个方法都对子/父之一有一个约束(在这种情况下:来自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();
}
}
差异很小,所以我想将两种方法合并在一起。
答案 0 :(得分:3)
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);
}
}
答案 1 :(得分:1)
除了T不是来自孩子的事实,我认为你想要使用
if (typeof(T).IsAssignableFrom(typeof(Parent))
...
否则它只会触发完全类型为Parent的东西,而不是派生类型。另外,我不认为==正确地重载了Type。我认为你需要使用.Equals()
注意:我可能已经向后收到了IsAssignableFrom。
答案 2 :(得分:1)
这部分代码没有意义:
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
,则肯定需要将约束定义为Parent
。
您说您的问题是您无法将orm.GetObject<T>
的输出转换为Child
。你是对的,你不能直接 - - 但是你可以先把它Parent
再然后再到{{ 1}}。我认为这应该有效:
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
。)