Comment puis-je appeler la méthode par défaut au lieu de l'implémentation concrète

9

Pourquoi le comportement des méthodes d'interface par défaut est-il modifié en C # 8? Dans le passé, le code suivant (lorsque la démonstration des méthodes d'interface par défaut n'était pas publiée):

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

a la sortie suivante:

Sortie console:

Je suis une méthode par défaut dans l'interface!
Je suis une méthode par défaut remplacée!

Mais avec la dernière version C # 8, le code ci-dessus produit la sortie suivante:

Sortie console:

Je suis une méthode par défaut remplacée!
Je suis une méthode par défaut remplacée!

N'importe qui peut m'expliquer pourquoi ce comportement a changé?

Remarque:

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

((IDefaultInterfaceMethod) anyClass).DefaultMethod(); // STILL the same problem!??
Bassam Alugili
la source
2
Il n'y avait pas de méthodes d'interface par défaut avant C # 8. La deuxième sortie est le cas attendu - lorsque vous implémentez une méthode d'interface, vous vous attendez à ce qu'elle soit appelée. Vous parlez peut-être d'une ancienne spécification? Je m'attends à ce qu'il soit abandonné car il casse le comportement attendu d'une méthode d'interface
Panagiotis Kanavos
3
Une meilleure question serait "comment puis-je appeler la méthode par défaut au lieu de l'implémentation concrète?" à laquelle la réponse est "vous ne pouvez pas encore, car la syntaxe base.DefaultMethod () a été supprimée de C # 8"
Panagiotis Kanavos
4
Voici la page de réunion de conception où les appels de base ont été discutés et abandonnés pour C # 8 Cut base() syntax for C# 8. We intend to bring this back in the next major release.. Cela nécessiterait un support d'exécution pour fonctionner correctement.
Panagiotis Kanavos
3
Une interface est toujours une interface. Lorsque j'implémente une méthode d'interface, je m'attends à ce que tous les clients appellent la méthode implémentée. Les clients ne devraient pas non plus se soucier de la classe qui implémente la méthode - ils ont une interface et ils l'appellent.
Panagiotis Kanavos
2
Quant à la syntaxe que vous avez publiée, elle doit provenir d'une proposition très ancienne - les modules DIM ne peuvent être appelés explicitement, comme les interfaces implémentées explicitement. Cependant, cette proposition utilise la syntaxe d'interface explicite pour ... faire le contraire de, virtualje suppose? Et éventuellement l'introduction d'un diamant d'héritage
Panagiotis Kanavos

Réponses:

6

Je soupçonne qu'une meilleure question serait:

Comment puis-je appeler la méthode par défaut au lieu de l'implémentation concrète?

La fonctionnalité a été planifiée mais a été coupée de C # 8 en avril 2019 , car une implémentation efficace nécessiterait le support du runtime. Cela n'a pas pu être ajouté à temps avant la sortie. La fonctionnalité devrait bien fonctionner à la fois pour C # et VB.NET - F # n'aime pas les interfaces de toute façon.

si BM n'est pas présent au moment de l'exécution, AM () sera appelé. Pour base () et les interfaces, cela n'est pas pris en charge par le runtime, donc l'appel lèvera une exception à la place. Nous aimerions ajouter un support pour cela dans le runtime, mais c'est trop cher pour faire cette version.

Nous avons quelques solutions de contournement, mais ils n'ont pas le comportement que nous voulons et ne sont pas le codegen préféré.

Notre implémentation pour C # est quelque peu réalisable, bien que ce ne soit pas exactement ce que nous aimerions, mais l'implémentation VB serait beaucoup plus difficile. De plus, l'implémentation de VB nécessiterait que les méthodes d'implémentation de l'interface soient une surface API publique.

Cela fonctionnera par le biais d'un base()appel similaire au fonctionnement des classes. Coopérer l'exemple de proposition:

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
la source
Je vais le laisser un moment avant de marquer la réponse. vous obtiendrez peut-être des votes positifs pour votre bon travail :-) merci!
Bassam Alugili le
1
@BassamAlugili uniquement parce que quelqu'un a demandé quelque chose de similaire il y a un mois. À l'époque, je pensais Why would you do that?. Puis j'ai découvert le procès
Panagiotis Kanavos