Bagaimana saya bisa memanggil metode default daripada implementasi konkret


9

Mengapa perilaku Metode Antarmuka Default diubah dalam C # 8? Di masa lalu kode berikut (Ketika metode antarmuka Default adalah demo tidak dirilis):

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

memiliki output sebagai berikut:

Output konsol:

Saya adalah metode default di antarmuka!
Saya adalah metode default yang diganti!

Tetapi dengan C # 8 versi terakhir kode di atas menghasilkan output berikut:

Output konsol:

Saya adalah metode default yang diganti!
Saya adalah metode default yang diganti!

Adakah yang bisa menjelaskan kepada saya mengapa perilaku ini diubah?

catatan:

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

((IDefaultInterfaceMethod) anyClass).DefaultMethod(); // STILL the same problem!??

2
Tidak ada metode standar antarmuka sebelum C # 8. Output kedua kasus diharapkan - ketika Anda menerapkan metode antarmuka, Anda berharap bahwa untuk dipanggil. Apakah Anda merujuk pada spesifikasi yang lebih lama? Saya berharap itu ditinggalkan karena itu merusak perilaku yang diharapkan dari metode antarmuka
Panagiotis Kanavos

3
Pertanyaan yang lebih baik adalah "bagaimana saya bisa memanggil metode default daripada implementasi konkret?" yang jawabannya adalah "Anda belum bisa, karena sintaksis base.DefaultMethod () dijatuhkan dari C # 8"
Panagiotis Kanavos

4
Inilah halaman rapat desain tempat panggilan dasar dibahas dan dijatuhkan untuk C # 8 Cut base() syntax for C# 8. We intend to bring this back in the next major release.. Ini akan membutuhkan dukungan runtime agar berfungsi dengan benar.
Panagiotis Kanavos

3
Antarmuka selalu merupakan antarmuka. Ketika saya menerapkan metode antarmuka saya berharap semua klien memanggil metode yang diimplementasikan. Klien seharusnya tidak peduli kelas mana yang mengimplementasikan metode ini - mereka mendapat antarmuka dan mereka menyebutnya.
Panagiotis Kanavos

2
Adapun sintaks yang Anda posting, itu harus dari proposal yang benar - benar tua - DIM hanya bisa disebut secara eksplisit, seperti antarmuka yang diimplementasikan secara eksplisit. Proposal itu, menggunakan sintaks antarmuka eksplisit untuk ... melakukan kebalikan dari yang virtualsaya kira? Dan mungkin memperkenalkan intan warisan
Panagiotis Kanavos

Jawaban:


6

Saya menduga pertanyaan yang lebih baik adalah:

Bagaimana saya bisa memanggil metode default daripada implementasi konkret?

Fitur ini direncanakan tetapi dipotong dari C # 8 pada April 2019 , karena implementasi yang efisien akan memerlukan dukungan dari runtime. Ini tidak dapat ditambahkan dalam waktu sebelum rilis. Fitur ini harus bekerja dengan baik untuk C # dan VB.NET - F # toh tidak menyukai antarmuka.

jika BM tidak ada pada saat run time, AM () akan dipanggil. Untuk base () dan antarmuka, ini tidak didukung oleh runtime, jadi panggilan akan membuang pengecualian. Kami ingin menambahkan dukungan untuk ini di runtime, tetapi terlalu mahal untuk membuat rilis ini.

Kami memiliki beberapa solusi, tetapi mereka tidak memiliki perilaku yang kita inginkan, dan bukan codegen yang disukai.

Implementasi kami untuk C # agak bisa dikerjakan, meskipun tidak persis seperti apa yang kami inginkan, tetapi implementasi VB akan jauh lebih sulit. Selain itu, implementasi untuk VB akan membutuhkan metode implementasi antarmuka untuk menjadi permukaan API publik.

Ini akan bekerja melalui base()panggilan yang mirip dengan cara kerja kelas. Mengooptasi contoh proposal:

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?
    }
}

Saya akan meninggalkannya sebentar sebelum menandai jawabannya. mungkin Anda akan mendapatkan suara untuk pekerjaan baik Anda :-) terima kasih!
Bassam Alugili

1
@BassamAlugili hanya karena seseorang menanyakan hal serupa sebulan yang lalu. Tapi saat itu saya kembali Why would you do that?. Kemudian saya menemukan notulen rapat
Panagiotis Kanavos
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.