Apa perbedaan antara mengimplementasikan Antarmuka secara eksplisit atau implisit?

64

Di Visual Studio saya dapat mengklik kanan pada antarmuka dan memilih untuk Menerapkan Antarmuka, atau Menerapkan Antarmuka Secara Eksplisit.

Cuplikan Layar Visual Studio

public class Test : ITest
{
    public string Id // Generated by Implement Interface
    {
        get { throw new NotImplementedException(); }
    }

    string ITest.Id // Generated by Implement Interface Explicitly
    {
        get { throw new NotImplementedException(); }
    }
}

Satu-satunya perbedaan yang saya lihat di antara keduanya adalah bahwa nama antarmuka ditambahkan ke properti antarmuka dan metode ketika mereka dibuat jika Anda memilih untuk mengimplementasikan antarmuka secara eksplisit.

Saya merasa itu membuat kode sedikit lebih mudah dibaca karena saya bisa melihat dari mana metode / properti itu berasal, namun apakah ini membuat perbedaan dalam bagaimana kelas digunakan atau dikompilasi? Dan apakah itu penting jika saya mengimplementasikan antarmuka saya secara implisit atau eksplisit?

Rachel
sumber

Jawaban:

51

Lihatlah jawaban teratas dari Andrew Barrett untuk "implementasi antarmuka eksplisit vs eksplisit" pada SO .

Pada dasarnya:

  • Tersirat: Anda mengakses metode antarmuka dan properti seolah-olah mereka adalah bagian dari kelas.
  • Eksplisit: Anda hanya dapat mengakses metode dan properti saat memperlakukan kelas sebagai antarmuka yang diterapkan.

Contoh kode:

Implisit:

Test t = new Test();
t.Id; // OK
((ITest)t).Id; // OK

Eksplisit:

Test t = new Test();
t.Id; // Not OK
((ITest)t).Id; // OK

Dalam hal "kapan" Anda harus mengimplementasikan antarmuka secara eksplisit, itu adalah ketika kelas Anda sudah memiliki metode dengan tanda tangan yang sama dengan salah satu metode antarmuka Anda, atau ketika kelas Anda mengimplementasikan beberapa antarmuka yang berbagi metode dengan tanda tangan yang sama tetapi kontrak yang tidak kompatibel.

Jalayn
sumber
1
Saya juga menemukan implementasi eksplisit berguna untuk memiliki semacam antarmuka "tersembunyi" dengan operasi yang tidak aman. Itu juga membuat panggilan ke metode-metode itu lebih menonjol yang merupakan hal yang baik untuk hal-hal yang tidak aman.
Tamás Szelei
Perlu juga disebutkan bahwa ada biaya kinerja untuk menggunakan antarmuka eksplisit, karena perlu kotak / unbox objek kapan saja Anda mereferensikan properti / metode. Karena itu, lebih baik menggunakan antarmuka implisit jika memungkinkan
Rachel
3
@ Rachel: Sejauh yang saya ketahui bahwa biaya kinerja hanya berlaku untuk tipe nilai.
Groky
8

Ada juga perbedaan dalam cara Anda memanggil metode.

Saat menggunakan implementasi antarmuka eksplisit , Anda harus menggunakan tipe antarmuka untuk memanggil implementasi spesifik itu.

Jadi, dalam memanggil kode Anda perlu menggunakan variabel tipe ITestuntuk mengakses ITest.Id.

Artikel Implementasi Antarmuka Eksplisit (Panduan Pemrograman C #) di MSDN memiliki contoh yang baik.

Oded
sumber
4

Ini memungkinkan Anda untuk mengimplementasikan dua antarmuka yang mendefinisikan metode yang sama. Namun, jika Anda secara eksplisit mengimplementasikan antarmuka, metode hanya dapat diakses ketika variabel diketik ke antarmuka eksplisit itu.

Lihat: Tutorial Implementasi Antarmuka Eksplisit

unholysampler
sumber
4

EDIT: Seharusnya tidak ada bedanya Anda tidak boleh melakukannya kecuali kelas Anda mengimplementasikan dua antarmuka dengan properti yang sama, karena Anda harus menggunakan antarmuka yang relevan sebelum Anda dapat mengakses anggota:

public interface ITest
{
    string Id { get; }
}

public interface IAlsoTest
{
    string Id { get; }
}

public interface ITestToo
{
    int Id { get; }
}

public class Test : ITest, IAlsoTest
{
    // Valid implicit implementation of BOTH interfaces
    public string Id
    {
        get { throw new NotImplementedException(); }
    }
}

public class TestSeparately : ITest, ITestToo
{
    // This way we can do different things depending
    // on which interface the callee called from.
    string ITest.Id
    {
        get { throw new NotImplementedException(); }
    }

    int ITestToo.Id
    {
        get { throw new NotImplementedException(); }
    }
}

public class TestOuch
{
    public void DoStuff()
    {
        var ts = new TestSeparately();

        // Works
        Console.WriteLine(((ITest)ts).Id);

        // Works
        Console.WriteLine(((ITestToo)ts).Id);

        // Not valid! Which one did we want to call?
        Console.WriteLine(ts.Id);
    }
}

Contoh penggunaan berlaku ketika Anda secara eksplisit mengimplementasikan anggota antarmuka bahkan jika Anda hanya menggunakan antarmuka tunggal (yang saya selalu lupa: S), jadi saya akan mencoba dan menghindari implementasi eksplisit bila memungkinkan, karena akan menyembunyikan anggota kelas jika mereka ' kembali tidak dilemparkan ke antarmuka yang tepat (yang cukup membingungkan).

Ed James
sumber
3

Berdasarkan jawaban Jalayan,

  • Tersirat: Anda mengakses metode antarmuka dan properti seolah-olah mereka adalah bagian dari kelas.
  • Eksplisit: Anda hanya dapat mengakses metode dan properti saat memperlakukan kelas sebagai antarmuka yang diterapkan.

masukkan deskripsi gambar di sini

Alexander Zaldostanov
sumber