具体的な実装の代わりにデフォルトのメソッドを呼び出すにはどうすればよいですか


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 より前のデフォルトのインターフェイスメソッドはありませんでした。2番目の出力は想定されるケースです。インターフェイスメソッドを実装すると、そのメソッドが呼び出されることが予想れます。おそらく古い仕様を参照していますか?インターフェイスメソッドの予想される動作を壊すため、放棄されたと
思い

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

回答:


6

私はもっ​​と良い質問があると思います:

具体的な実装の代わりにデフォルトのメソッドを呼び出すにはどうすればよいですか?

機能は計画されましたが、効率的な実装にはランタイムからのサポートが必要になるため、2019年4月にC#8から削除されました。これはリリース前に時間内に追加できませんでした。この機能はC#とVB.NETの両方で適切に機能する必要があります-F#はとにかくインターフェイスが好きではありません。

BMが実行時に存在しない場合、AM()が呼び出されます。base()とインターフェースの場合、これはランタイムでサポートされていないため、呼び出しは代わりに例外をスローします。ランタイムでのサポートを追加したいのですが、このリリースを作成するにはコストがかかりすぎます。

いくつかの回避策がありますが、それらには私たちが望む振る舞いがなく、推奨されるcodegenではありません。

C#の実装は、私たちが望むものではありませんが、いくらか機能しますが、VBの実装ははるかに困難です。さらに、VBの実装では、インターフェース実装メソッドがパブリックAPIサーフェスである必要があります。

これはbase()クラスの動作同様呼び出しを通じて動作します。提案の例をcoooping:

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は、誰かが 1か月前に同様の質問をしたからです。当時はでもWhy would you do that?。その後、会議の議事録を見つけました
Panagiotis Kanavos
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.