Why does the this generic function not call the overriden function

If I have a base class

class Foo : IClonable {

    public object virtual Clone(){ return new Foo(); }  
}

and a child class incorrectly overriding clone with new instead of override. It's a simplification of a bug in a third party library I'm trying to work around.

class Bar : Foo {

    public new Clone() { return new Bar(); }
}

and then I have two methods

public static T Bang(T source)
where T : Foo
{
    return (T) source.Clone();
}

and

public static Bar Bang(Bar source)
{
    return (Bar) source.Clone();
}

now if I invoke the first one with an instance of Bar I get a Foo back. If I invoke the second I get Bar back.

I'm curious as to why the generic version doesn't get the new version of Clone() but rather the inherited version.

Is it that the type T is erased after the constraints are met and then it just behaves using the base class?

Jon Skeet
people
quotationmark

Is it that the type T is erased after the constraints are met and then it just behaves using the base class?

It depends on what you mean by "the type T is erased". It's not erased in the same way that it is in Java - the type argument is available at execution time, so if you write:

Console.WriteLine(typeof(T));

that will print Bar.

However, the compiler needs to determine which method to call when it compiles your first Bang method is that the value is of type Foo or some subtype. It has to generate IL calling one method based on that. It's not like the compiler generates a new Bang method for every different T, using the actual type T to perform method resolution etc.

In other words, as far as the compiler is concerned your method is equivalent to:

public static T Bang<T>(Foo source)
where T : Foo
{
    return (T) source.Clone();
}

Note the change of the parameter type from T to Foo, because that's all the information the compiler has to go on.

(I'm assuming that you understand that your two Clone methods are mostly unrelated as far as the compiler and CLR are concerned; they happen to have the same name, but one doesn't override the other polymorphically.)

people

See more on this question at Stackoverflow