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

Почему в 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 ответ

Решение

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

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

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

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

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

Наша реализация для C# в некоторой степени работоспособна, хотя и не совсем то, что нам хотелось бы, но реализация VB была бы намного сложнее. Более того, реализация VB потребует, чтобы методы реализации интерфейса были общедоступной поверхностью 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?
    }
}
Другие вопросы по тегам