Como posso chamar o método padrão em vez da implementação concreta

9

Por que o comportamento dos Métodos de Interface Padrão foi alterado no C # 8? No passado, o código a seguir (quando os métodos de interface padrão foram demo não lançados):

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();
    }
}

tem a seguinte saída:

Saída do console:

Eu sou um método padrão na interface!
Eu sou um método padrão substituído!

Mas com a última versão do C # 8, o código acima está produzindo a seguinte saída:

Saída do console:

Eu sou um método padrão substituído!
Eu sou um método padrão substituído!

Alguém pode me explicar por que esse comportamento mudou?

Nota:

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

((IDefaultInterfaceMethod) anyClass).DefaultMethod(); // STILL the same problem!??
Bassam Alugili
fonte
2
Não havia métodos de interface padrão antes do C # 8. A segunda saída é o caso esperado - quando você implementa um método de interface, espera que isso seja chamado. Você está se referindo a uma especificação mais antiga, talvez? Espero que tenha sido abandonado porque quebra o comportamento esperado de um método de interface
Panagiotis Kanavos
3
Uma pergunta melhor seria "como posso chamar o método padrão em vez da implementação concreta?" para a qual a resposta é "você ainda não pode, porque a sintaxe base.DefaultMethod () foi removida do C # 8"
Panagiotis Kanavos
4
Aqui está a página da reunião de design em que as chamadas básicas foram discutidas e descartadas para o C # 8 Cut base() syntax for C# 8. We intend to bring this back in the next major release.. Isso exigiria suporte de tempo de execução para funcionar corretamente.
Panagiotis Kanavos 15/01
3
Uma interface é sempre uma interface. Ao implementar um método de interface, espero que todos os clientes chamem o método implementado. Os clientes também não devem se importar com a classe que implementa o método - eles têm uma interface e a chamam.
Panagiotis Kanavos 15/01
2
Quanto à sintaxe que você postou, ela deve ser de uma proposta muito antiga - os DIMs só podem ser chamados explicitamente, como interfaces implementadas explicitamente. Essa proposta, no entanto, usa a sintaxe explícita da interface para ... fazer o oposto de virtualeu acho? E possivelmente introduzindo um diamante de herança
Panagiotis Kanavos

Respostas:

6

Eu suspeito que uma pergunta melhor seria:

Como posso chamar o método padrão em vez da implementação concreta?

O recurso foi planejado, mas foi cortado do C # 8 em abril de 2019 , porque uma implementação eficiente exigiria suporte do tempo de execução. Isso não pôde ser adicionado antes do lançamento. O recurso teria que funcionar bem para C # e VB.NET - F # não gosta de interfaces de qualquer maneira.

se BM não estiver presente no tempo de execução, AM () será chamado. Para base () e interfaces, isso não é suportado pelo tempo de execução; portanto, a chamada lançará uma exceção. Gostaríamos de adicionar suporte para isso no tempo de execução, mas é muito caro fazer esse lançamento.

Temos algumas soluções alternativas, mas elas não têm o comportamento que queremos e não são o codegen preferido.

Nossa implementação para C # é algo viável, embora não seja exatamente o que gostaríamos, mas a implementação do VB seria muito mais difícil. Além disso, a implementação do VB exigiria que os métodos de implementação da interface fossem uma superfície pública da API.

Ele funcionará através de uma base()chamada semelhante à forma como as aulas funcionam. Copiando o exemplo da proposta:

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
fonte
Vou deixar por um tempo antes de marcar a resposta. talvez você receba alguns votos positivos pelo seu bom trabalho :-) obrigado!
Bassam Alugili 15/01
11
@BassamAlugili apenas porque alguém perguntou algo semelhante há um mês. Naquela época eu pensei Why would you do that?. Então eu descobri a ata da reunião
Panagiotis Kanavos