Как я могу вызвать метод по умолчанию вместо конкретной реализации - PullRequest
9 голосов
/ 15 января 2020

Почему поведение методов интерфейса по умолчанию изменено в C# 8? В прошлом следующий код (когда демонстрационные методы интерфейса по умолчанию не были выпущены):

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

имеет следующий вывод:

Консольный вывод:

Я метод по умолчанию в интерфейсе!
Я переопределенный метод по умолчанию!

Но с последней версией C# 8 приведенный выше код создает следующий вывод:

Вывод на консоль:

Я переопределен по умолчанию метод!
Я переопределенный метод по умолчанию!

Кто-нибудь может объяснить мне, почему это поведение изменилось?

Примечание:

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

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

1 Ответ

6 голосов
/ 15 января 2020

Я подозреваю, что лучшим вопросом будет:

Как я могу вызвать метод по умолчанию вместо конкретной реализации?

Функция была запланирована, но была сокращение от C# 8 в апреле 2019 , потому что эффективная реализация потребует поддержки из среды выполнения. Это не может быть добавлено вовремя перед выпуском. Эта функция должна хорошо работать как для C#, так и для VB. NET - F # все равно не любит интерфейсы.

, если BM не присутствует во время выполнения, AM () будет называется. Для base () и интерфейсов это не поддерживается средой выполнения, поэтому вызов вместо этого вызовет исключение. Мы хотели бы добавить поддержку для этого во время выполнения, но сделать этот выпуск слишком дорого.

У нас есть некоторые обходные пути, но они не работают так, как мы хотим, и не являются предпочтительным кодом ,

Наша реализация для C# несколько работоспособна, хотя и не совсем то, что нам хотелось бы, но реализация на VB была бы намного сложнее. Более того, реализация для VB потребует, чтобы методы реализации интерфейса были опубликованы c поверхность API.

Это будет работать через base() вызов подобно тому, как работают классы , Пример предложения:

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?
    }
}
...