如何调用默认方法而不是具体实现


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 之前没有默认的接口方法。第二个输出是预期的情况-实现接口方法时,您希望被调用。您是在指较旧的规范吗?我希望它被放弃,因为它破坏了接口方法的预期行为
Panagiotis Kanavos

3
更好的问题是“如何调用默认方法而不是具体实现?” 答案是“您还不能,因为base.DefaultMethod()语法已从C#8中删除”
Panagiotis Kanavos

4
这是设计会议页面,讨论了C#8的基本调用Cut base() syntax for C# 8. We intend to bring this back in the next major release.。这将需要运行时支持才能正常工作。
Panagiotis Kanavos

3
接口始终是接口。当我实现接口方法时,我希望所有客户端都调用已实现的方法。客户也不必关心哪个类实现了该方法-他们有一个接口并调用它。
Panagiotis Kanavos

2
至于您发布的语法,它必须来自一个非常古老的建议-DIM只能显式调用,就像显式实现的接口一样。该提案虽然使用显式接口语法......做了相反virtual我猜?并可能引入继承钻石
Panagiotis Kanavos

Answers:


6

我怀疑一个更好的问题是:

如何调用默认方法而不是具体实现?

该功能是计划中的,但于2019年4月从C#8中删除,因为有效的实现需要运行时的支持。无法在发布前及时添加。该功能必须同时适用于C#和VB.NET-F#仍然不喜欢接口。

如果运行时不存在BM,则将调用AM()。对于base()和interfaces,运行时不支持此功能,因此调用将引发异常。我们想在运行时中添加对此的支持,但是发布此版本太昂贵了。

我们有一些解决方法,但是它们没有我们想要的行为,也不是首选的代码生成器。

尽管不是我们想要的那样,我们对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?
    }
}

在标记答案之前,我会保留一会儿。也许您会因为您的出色工作而获得投票:-)谢谢!
巴萨姆·阿鲁吉利

1
@BassamAlugili只是因为一个月前有人问过类似的问题。那时候我虽然Why would you do that?。然后我找到了会议记录
Panagiotis Kanavos
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.