泛型:访问新成员,而不是隐藏成员

时间:2009-04-21 21:33:22

标签: .net generics

我遇到了泛型和新成员的问题。我写了一个泛型类,它对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); }

3 个答案:

答案 0 :(得分:7)

没有。编译器生成的调用是在编译时知道的成员。这是由ObjectA公开的成员。

使用虚拟/重写方法,你没有使用普通继承的原因吗?

顺便说一下,这是另一个相同类型的例子 - 即使T在调用stringFoousing 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中会有一个方法地址,它的行为就像你认为的那样。