我遇到了泛型和新成员的问题。我写了一个泛型类,它对ObjectA类型的对象进行操作。 ObjectB派生自ObjectA并隐藏了ObjectA的一些成员。当我提供ObjectB的类型作为泛型类的类型参数时,我希望当我调用ObjectB隐藏的任何成员时,我将调用ObjectB的实现。但是,CLR仍然调用隐藏成员(ObjectA的实现)。这似乎不合逻辑,因为我明确地向泛型类提供了ObjectB的类型。这是仿制药本身的问题,还是我做错了什么?
编辑:不幸的是,我无法访问ObjectA的源代码,而我想覆盖的成员不是虚拟的。如果我可以访问ObjectA的源代码,我会将该成员设为虚拟,但由于我不能这样做,我“覆盖”该成员的唯一选择是通过“new”关键字。
class GenericClass<T> where T : ObjectA
{
public void DoWork(T item)
{
// When type parameter 'T' is ObjectB, should get ObjectB's implementation
item.Invoke();
}
}
class ObjectA
{
public void Invoke()
{
// A's implementation...
}
}
class ObjectB : ObjectA
{
public new void Invoke()
{
// B's implementation...
}
}
static void Main()
{
GenericClass<ObjectB> genericClass = new GenericClass<ObjectB>();
ObjectB objectB = new ObjectB();
genericClass.DoWork(objectB);
}
class GenericClass<T> where T : ObjectA
{
public void DoWork(T item)
{
// When type parameter 'T' is ObjectB, should get ObjectB's implementation
item.Invoke();
}
}
class ObjectA
{
public void Invoke()
{
// A's implementation...
}
}
class ObjectB : ObjectA
{
public new void Invoke()
{
// B's implementation...
}
}
static void Main()
{
GenericClass<ObjectB> genericClass = new GenericClass<ObjectB>();
ObjectB objectB = new ObjectB();
genericClass.DoWork(objectB);
}
答案 0 :(得分:7)
没有。编译器生成的调用是在编译时知道的成员。这是由ObjectA
公开的成员。
使用虚拟/重写方法,你没有使用普通继承的原因吗?
顺便说一下,这是另一个相同类型的例子 - 即使T
在调用string
时Foo
为using System;
class Test
{
static bool Foo<T>(T first, T second)
where T : class
{
return first == second;
}
static void Main()
{
string x = "hello";
string y = new string(x.ToCharArray());
Console.WriteLine(Foo(x, y));
}
}
,也不会使用字符串的重载==运算符}:
{{1}}
答案 1 :(得分:0)
这可能不是你问题的答案,但我不认为你的方法有意义(可能是因为我只看到一个简化的例子)。
我建议使用以下方法:
class ObjectA
{
public virtual void Invoke()
{
// do some work
}
}
class ObjectB : ObjectA
{
public override void Invoke()
{
// do some other work
}
}
class GenericNotNeededClass
{
public void DoWork(ObjectA item)
{
item.Invoke();
}
}
static void Main()
{
GenericNotNeededClass nonGenericClass = new GenericNotNeededClass();
ObjectB objectB = new ObjectB();
nonGenericClass.DoWork(objectB);
}
我相信代码会根据您的示例代码执行您要查找的内容。
答案 2 :(得分:0)
您将T定义为您的泛型的ObjectA类型。如果Invoke()是虚拟的,它将按照您的思维方式工作,但由于它不是,您的泛型调用ObjectA实现,因为这是T被定义为。
没有虚拟方法表条目指向Invoke()的ObjectB实现,因此这是运行时可以调用的所有内容。如果它是一个虚方法,那么VMT中会有一个方法地址,它的行为就像你认为的那样。