¿Cómo puedo llamar al método predeterminado en lugar de la implementación concreta?

9

¿Por qué se cambia el comportamiento de los métodos de interfaz predeterminados en C # 8? En el pasado, el siguiente código (cuando no se lanzó la demostración de los métodos de interfaz predeterminados):

interface IDefaultInterfaceMethod
{
    // By default, this method will be virtual, and the virtual keyword can be here used!
    virtual void DefaultMethod()
    {
        Console.WriteLine("I am a default method in the interface!");
    }

}

interface IOverrideDefaultInterfaceMethod : IDefaultInterfaceMethod
{
    void IDefaultInterfaceMethod.DefaultMethod()
    {
        Console.WriteLine("I am an overridden default method!");
    }
}

class AnyClass : IDefaultInterfaceMethod, IOverrideDefaultInterfaceMethod
{
}

class Program
{
    static void Main()
    {
        IDefaultInterfaceMethod anyClass = new AnyClass();
        anyClass.DefaultMethod();

        IOverrideDefaultInterfaceMethod anyClassOverridden = new AnyClass();
        anyClassOverridden.DefaultMethod();
    }
}

tiene el siguiente resultado:

Salida de consola:

¡Soy un método predeterminado en la interfaz!
¡Soy un método predeterminado anulado!

Pero con la última versión de C # 8, el código anterior produce el siguiente resultado:

Salida de consola:

¡Soy un método predeterminado anulado!
¡Soy un método predeterminado anulado!

¿Alguien puede explicarme por qué se cambia este comportamiento?

Nota:

IDefaultInterfaceMethod anyClass = new AnyClass(); anyClass.DefaultMethod();

((IDefaultInterfaceMethod) anyClass).DefaultMethod(); // STILL the same problem!??
Bassam Alugili
fuente
2
No había métodos de interfaz predeterminados antes de C # 8. El segundo resultado es el caso esperado: cuando implementa un método de interfaz, espera que se llame. ¿Te refieres a una especificación anterior quizás? Espero que haya sido abandonado porque rompe el comportamiento esperado de un método de interfaz
Panagiotis Kanavos
3
Una mejor pregunta sería "¿cómo puedo llamar al método predeterminado en lugar de la implementación concreta?" a lo que la respuesta es "todavía no puedes, porque la sintaxis base.DefaultMethod () se eliminó de C # 8"
Panagiotis Kanavos
44
Aquí está la página de la reunión de diseño donde se discutieron y descartaron las llamadas de base para C # 8 Cut base() syntax for C# 8. We intend to bring this back in the next major release.. Esto requeriría soporte de tiempo de ejecución para funcionar correctamente.
Panagiotis Kanavos
3
Una interfaz es una interfaz siempre. Cuando implemento un método de interfaz, espero que todos los clientes llamen al método implementado. A los clientes tampoco les debería importar qué clase implementa el método: obtuvieron una interfaz y la llaman.
Panagiotis Kanavos
2
En cuanto a la sintaxis que publicó, debe ser de una propuesta muy antigua: los DIM solo pueden llamarse explícitamente, como las interfaces implementadas explícitamente. Sin embargo, esa propuesta utiliza la sintaxis explícita de la interfaz para ... ¿hacer lo contrario de lo virtualque supongo? Y posiblemente introduciendo un diamante de herencia
Panagiotis Kanavos

Respuestas:

6

Sospecho que una mejor pregunta sería:

¿Cómo puedo llamar al método predeterminado en lugar de la implementación concreta?

La función se planificó, pero se eliminó de C # 8 en abril de 2019 , porque una implementación eficiente requeriría soporte del tiempo de ejecución. Esto no se pudo agregar a tiempo antes del lanzamiento. La característica tendría que funcionar bien tanto para C # como para VB.NET: a F # no le gustan las interfaces de todos modos.

si BM no está presente en el tiempo de ejecución, se llamará a AM (). Para base () e interfaces, esto no es compatible con el tiempo de ejecución, por lo que la llamada generará una excepción. Nos gustaría agregar soporte para esto en tiempo de ejecución, pero es demasiado costoso hacer esta versión.

Tenemos algunas soluciones, pero no tienen el comportamiento que queremos y no son el codegen preferido.

Nuestra implementación para C # es algo viable, aunque no es exactamente lo que nos gustaría, pero la implementación de VB sería mucho más difícil. Además, la implementación de VB requeriría que los métodos de implementación de la interfaz sean una superficie API pública.

Funcionará a través de una base()llamada similar a cómo funcionan las clases. Copiando el ejemplo de propuesta:

interface I1
{ 
    void M(int) { }
}

interface I2
{
    void M(short) { }
}

interface I3
{
    override void I1.M(int) { }
}

interface I4 : I3
{
    void M2()
    {
        base(I3).M(0) // What does this do?
    }
}
Panagiotis Kanavos
fuente
Lo dejaré por un tiempo antes de marcar la respuesta. tal vez obtendrá algunos votos positivos por su buen trabajo :-) ¡gracias!
Bassam Alugili
1
@BassamAlugili solo porque alguien preguntó algo similar hace un mes. En aquel entonces, sin embargo Why would you do that?. Luego descubrí las minutas de la reunión
Panagiotis Kanavos,