Як я можу викликати метод за замовчуванням замість конкретної реалізації


9

Чому поведінка методів інтерфейсу за замовчуванням змінюється в 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!??

2
Не було стандартних методів інтерфейсу до C # 8. Другий вихід - очікуваний випадок - коли ви реалізуєте метод інтерфейсу, ви очікуєте, що він буде викликаний. Можливо, ви маєте на увазі старішу специфікацію? Я очікую, що його відмовили, оскільки він порушує очікувану поведінку методу інтерфейсу
Панайотис Канавос

3
Кращим питанням буде "як я можу викликати метод за замовчуванням замість конкретної реалізації?" на що відповідь "Ви ще не можете, тому що синтаксис base.DefaultMethod () було скинуто з C # 8"
Панайотис Канавос

4
Ось сторінка дизайнерських зустрічей, де обговорювались базові дзвінки та відмовлялися від C # 8 Cut base() syntax for C# 8. We intend to bring this back in the next major release.. Для правильної роботи це потребує підтримки для виконання.
Панайотис Канавос

3
Інтерфейс - це інтерфейс завжди. Коли я реалізую метод інтерфейсу, я очікую, що всі клієнти зателефонують у реалізований метод. Клієнтам не повинно бути байдуже, який клас реалізує метод також - вони отримали інтерфейс і вони його називають.
Панайотис Канавос

2
Що стосується опублікованого вами синтаксису, він повинен бути з дійсно старої пропозиції - DIM-адреси можна викликати лише явно, як явно реалізовані інтерфейси. Ця пропозиція , хоча, використовує явний синтаксис інтерфейсу для ... зробіть протилежні від virtualI здогадуються? І, можливо, ввести алмаз у спадок
Панайотис Канавос

Відповіді:


6

Я підозрюю, що кращим питанням буде:

Як я можу викликати метод за замовчуванням замість конкретної реалізації?

Ця функція була запланована, але її скоротили з 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?
    }
}

Я залишу його на деякий час, перш ніж позначити відповідь. можливо, ви отримаєте кілька голосів за свою добру роботу :-) дякую!
Bassam Alugili

1
@BassamAlugili лише тому, що хтось запитав щось подібне місяць тому. Тоді я хоч Why would you do that?. Тоді я дізнався протокол зустрічі
Панайотис Канавос
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.