C # y generics: ¿por qué se llama método a la clase base en lugar de método nuevo a la clase derivada?

Si el argumento de tipo genérico (de una clase que llama o un método de llamada) está restringido conwhere T : Base el nuevo método en T == Derivado no se llama, en lugar del método en Base se llama.

¿Por qué se ignora el tipo T para la llamada de método, aunque se debe conocer antes del tiempo de ejecución?

Actualizar: PERO, cuando la restricción está utilizando una interfaz comowhere T : IBase se llama al método en la clase Base (no al método en la interfaz, que también es imposible).
¡Así que eso significa que el sistema realmente puede detectar los tipos que van más allá e ir más allá de la restricción de tipo! Entonces, ¿por qué no va más allá de la restricción de tipo en el caso de una restricción de tipo de clase?
¿Significa eso que el método en la clase Base que implementa la interfaz tiene una palabra clave de reemplazo implícita para el método?

Código de prueba:

public interface IBase
{
    void Method();
}

public class Base : IBase 
{
    public void Method()
    {

    }
}

public class Derived : Base
{
    public int i = 0;

    public new void Method()
    {
        i++;
    }
}

public class Generic<T>
    where T : Base
{
    public void CallMethod(T obj)
    {
        obj.Method();  //calls Base.Method()
    }

    public void CallMethod2<T2>(T2 obj)
        where T2 : T
    {
        obj.Method();  //calls Base.Method()
    }
}

public class GenericWithInterfaceConstraint<T>
    where T : IBase
{
    public void CallMethod(T obj)
    {
        obj.Method();  //calls Base.Method()
    }

    public void CallMethod2<T2>(T2 obj)
        where T2 : T
    {
        obj.Method();  //calls Base.Method()
    }
}

public class NonGeneric
{
    public void CallMethod(Derived obj)
    {
        obj.Method();  //calls Derived.Method()
    }

    public void CallMethod2<T>(T obj)
        where T : Base
    {
        obj.Method();  //calls Base.Method()
    }

    public void CallMethod3<T>(T obj)
        where T : IBase
    {
        obj.Method();  //calls Base.Method()
    }
}

public class NewMethod
{
    unsafe static void Main(string[] args)
    {
        Generic<Derived> genericObj = new Generic<Derived>();
        GenericWithInterfaceConstraint<Derived> genericObj2 = new GenericWithInterfaceConstraint<Derived>();
        NonGeneric nonGenericObj = new NonGeneric();
        Derived obj = new Derived();

        genericObj.CallMethod(obj);  //calls Base.Method()
        Console.WriteLine(obj.i);

        genericObj.CallMethod2(obj);  //calls Base.Method()
        Console.WriteLine(obj.i);

        genericObj2.CallMethod(obj);  //calls Base.Method()
        Console.WriteLine(obj.i);

        genericObj2.CallMethod2(obj);  //calls Base.Method()
        Console.WriteLine(obj.i);

        nonGenericObj.CallMethod(obj);  //calls Derived.Method()
        Console.WriteLine(obj.i);

        nonGenericObj.CallMethod2(obj);  //calls Base.Method()
        Console.WriteLine(obj.i);

        nonGenericObj.CallMethod3(obj);  //calls Base.Method()
        Console.WriteLine(obj.i);

        obj.Method();  //calls Derived.Method()
        Console.WriteLine(obj.i);
    }
}

Salida:

0
0
0
0
1
1
1
2

Respuestas a la pregunta(4)

Su respuesta a la pregunta