Come posso chiamare il metodo predefinito invece dell'implementazione concreta


9

Perché il comportamento dei metodi di interfaccia predefiniti è cambiato in C # 8? In passato il seguente codice (quando non sono stati rilasciati i metodi dell'interfaccia predefinita):

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

ha il seguente output:

Uscita console:

Sono un metodo predefinito nell'interfaccia!
Sono un metodo predefinito ignorato!

Ma con l'ultima versione di C # 8 il codice sopra sta producendo il seguente output:

Uscita console:

Sono un metodo predefinito ignorato!
Sono un metodo predefinito ignorato!

Qualcuno può spiegarmi perché questo comportamento è cambiato?

Nota:

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

((IDefaultInterfaceMethod) anyClass).DefaultMethod(); // STILL the same problem!??

2
Non c'erano metodi di interfaccia predefiniti prima di C # 8. Il secondo output è il caso previsto: quando si implementa un metodo di interfaccia, ci si aspetta che venga chiamato. Ti riferisci forse a una specifica precedente? Mi aspetto che sia stato abbandonato perché interrompe il comportamento previsto di un metodo di interfaccia
Panagiotis Kanavos

3
Una domanda migliore sarebbe "come posso chiamare il metodo predefinito invece dell'implementazione concreta?" a cui la risposta è "non puoi ancora, perché la sintassi base.DefaultMethod () è stata eliminata da C # 8"
Panagiotis Kanavos

4
Ecco la pagina della riunione di progettazione in cui le chiamate di base sono state discusse e rilasciate per C # 8 Cut base() syntax for C# 8. We intend to bring this back in the next major release.. Ciò richiederebbe il supporto del runtime per funzionare correttamente.
Panagiotis Kanavos il

3
Un'interfaccia è sempre un'interfaccia. Quando implemento un metodo di interfaccia, mi aspetto che tutti i client chiamino il metodo implementato. Ai clienti non dovrebbe interessare nemmeno quale classe implementa il metodo: hanno un'interfaccia e la chiamano.
Panagiotis Kanavos il

2
Per quanto riguarda la sintassi che hai pubblicato, deve provenire da una proposta molto vecchia: i DIM possono essere chiamati esplicitamente, come interfacce esplicitamente implementate. Quella proposta però usa la sintassi dell'interfaccia esplicita per ... fare il contrario di virtualimmagino? E forse introducendo un diamante ereditario
Panagiotis Kanavos il

Risposte:


6

Ho il sospetto che una domanda migliore sarebbe:

Come posso chiamare il metodo predefinito invece dell'implementazione concreta?

La funzionalità è stata pianificata ma è stata tagliata da C # 8 nell'aprile 2019 , poiché un'implementazione efficiente richiederebbe il supporto del runtime. Questo non può essere aggiunto in tempo prima del rilascio. La funzione dovrebbe funzionare bene sia per C # che per VB.NET - Ad F # non piacciono comunque le interfacce.

se BM non è presente in fase di esecuzione, verrà chiamato AM (). Per base () e interfacce, questo non è supportato dal runtime, quindi la chiamata genererà un'eccezione. Vorremmo aggiungere il supporto per questo in fase di esecuzione, ma è troppo costoso realizzare questa versione.

Abbiamo alcune soluzioni alternative, ma non hanno il comportamento che vogliamo e non sono il codegen preferito.

La nostra implementazione per C # è in qualche modo praticabile, sebbene non esattamente quello che vorremmo, ma l'implementazione di VB sarebbe molto più difficile. Inoltre, l'implementazione per VB richiederebbe che i metodi di implementazione dell'interfaccia siano di superficie API pubblica.

Funzionerà attraverso una base()chiamata simile a come funzionano le classi. Cooping dell'esempio di 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?
    }
}

Lascerò per un po 'prima di segnare la risposta. forse otterrai dei voti positivi per il tuo buon lavoro :-) grazie!
Bassam Alugili,

1
@BassamAlugili solo perché qualcuno ha chiesto qualcosa di simile un mese fa. Allora ho pensato Why would you do that?. Poi ho scoperto i verbali della riunione
Panagiotis Kanavos, il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.