10

Why is the behavior of Default Interface Methods changed in C# 8? In the past the following code (When the Default interface methods was demo not released):

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

has the following output:

Console output:

I am a default method in the interface!
I am an overridden default method!

But with the C# 8 last version the code above is producing the following output:

Console output:

I am an overridden default method!
I am an overridden default method!

Anyone can explain to me why this behavior is changed?

Note:

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

((IDefaultInterfaceMethod) anyClass).DefaultMethod(); // STILL the same problem!??
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
Bassam Alugili
  • 16,345
  • 7
  • 52
  • 70
  • 2
    There were no default interface methods *before* C# 8. The second output is the expected case - when you implement an interface method, you expect *that* to be called. Are you referring to an older specification perhaps? I expect it was abandoned because it breaks the expected behavior of an interface method – Panagiotis Kanavos Jan 15 '20 at 09:15
  • 3
    A better question would be "how can I call the default method instead of the concrete implementation?" to which the answer is "you can't yet, because the base.DefaultMethod() syntax was dropped from C# 8" – Panagiotis Kanavos Jan 15 '20 at 09:16
  • 4
    [Here is the design meeting page](https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-04-29.md#default-interface-implementations-and-base-calls) where base calls were discussed and dropped for C# 8 `Cut base() syntax for C# 8. We intend to bring this back in the next major release.`. This would require runtime support to work properly. – Panagiotis Kanavos Jan 15 '20 at 09:18
  • @PanagiotisKanavos thank you! I know the official release is in the C# 8, but in the past we seen a demo version on (https://sharplab.io/ and with VS preview) I have test it in the past. what it make more sense for you the fist behavior or the second one and why? – Bassam Alugili Jan 15 '20 at 09:18
  • 3
    An interface is an interface always. When I implement an interface method I expect *all* clients to call the implemented method. *Clients* shouldn't care which class implements the method either - they got an interface and they call it. – Panagiotis Kanavos Jan 15 '20 at 09:20
  • @PanagiotisKanavos thank you I will read that and come back to you. – Bassam Alugili Jan 15 '20 at 09:21
  • @PanagiotisKanavos answer the question! and I will mark your answer! thank you I have forget that the base() syntax is temporarily removed! – Bassam Alugili Jan 15 '20 at 09:27
  • 2
    As for the syntax you posted, it must be from a *really* old proposal - DIMs can only be called explicitly, like explicitly implemented interfaces. That proposal though, uses the explicit interface syntax to ... do the *opposite* of `virtual` I guess? And possibly introducing an inheritance diamond – Panagiotis Kanavos Jan 15 '20 at 09:27
  • 1
    I just now remembered that I've tried the same syntax to call base method implementations - the overall concept is confusing *for now*. It took Java folks a bit of time to get comfortable with default members too – Panagiotis Kanavos Jan 15 '20 at 09:29
  • @PanagiotisKanavos correct i did it before long time! https://www.infoq.com/articles/default-interface-methods-cs8/ – Bassam Alugili Jan 15 '20 at 09:29

1 Answers1

6

I suspect a better question would be:

How can I call the default method instead of the concrete implementation?

The feature was planned but was cut from C# 8 in April 2019, because an efficient implementation would require support from the runtime. This couldn't be added in time before release. The feature would have to work well both for C# and VB.NET - F# doesn't like interfaces anyway.

if B.M is not present at run time, A.M() will be called. For base() and interfaces, this is not supported by the runtime, so the call will throw an exception instead. We'd like to add support for this in the runtime, but it is too expensive to make this release.

We have some workarounds, but they do not have the behavior we want, and are not the preferred codegen.

Our implementation for C# is somewhat workable, although not exactly what we would like, but the VB implementation would be much more difficult. Moreover, the implementation for VB would require the interface implementation methods to be public API surface.

It will work through a base() call similar to how classes work. Coopying the proposal example :

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?
    }
}
Community
  • 1
  • 1
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • I will leave it for a while before mark the answer. maybe you will get some up-votes for your good work :-) thank you! – Bassam Alugili Jan 15 '20 at 09:43
  • 1
    @BassamAlugili only because [someone asked something similar](https://stackoverflow.com/questions/59387322/making-member-virtual-prevents-calling-default-interface-implementation-and-caus) a month ago. Back then I though `Why would you do that?`. Then I found out the meeting minutes – Panagiotis Kanavos Jan 15 '20 at 09:55