Saya menggunakan implementasi antarmuka eksplisit sebagian besar waktu. Inilah alasan utamanya.
Refactoring lebih aman
Saat mengganti antarmuka, lebih baik jika kompilator dapat memeriksanya. Ini lebih sulit dengan implementasi implisit.
Dua kasus umum muncul di pikiran:
Menambahkan fungsi ke antarmuka, di mana kelas yang sudah ada yang mengimplementasikan antarmuka ini sudah memiliki metode dengan tanda tangan yang sama dengan yang baru . Ini dapat menyebabkan perilaku yang tidak terduga, dan telah menggigit saya beberapa kali. Sulit untuk "melihat" ketika debugging karena fungsi itu kemungkinan tidak terletak dengan metode antarmuka lain dalam file (masalah mendokumentasikan diri disebutkan di bawah).
Menghapus fungsi dari antarmuka . Metode yang diimplementasikan secara implisit akan tiba-tiba mati kode, tetapi metode yang diimplementasikan secara eksplisit akan tertangkap oleh kesalahan kompilasi. Bahkan jika kode mati itu baik untuk disimpan, saya ingin dipaksa untuk memeriksanya dan mempromosikannya.
Sangat disayangkan bahwa C # tidak memiliki kata kunci yang memaksa kita untuk menandai metode sebagai implementasi implisit, sehingga kompiler dapat melakukan pemeriksaan tambahan. Metode virtual tidak memiliki salah satu masalah di atas karena diperlukan penggunaan 'menimpa' dan 'baru'.
Catatan: untuk antarmuka yang diperbaiki atau jarang berubah (biasanya dari vendor API), ini bukan masalah. Untuk antarmuka saya sendiri, saya tidak bisa memprediksi kapan / bagaimana mereka akan berubah.
Ini mendokumentasikan diri
Jika saya melihat 'public bool Execute ()' di kelas, itu akan membutuhkan kerja ekstra untuk mengetahui bahwa itu adalah bagian dari antarmuka. Seseorang mungkin harus mengomentari dengan mengatakannya, atau memasukkannya ke dalam kelompok implementasi antarmuka lain, semuanya di bawah suatu wilayah atau mengelompokkan komentar yang mengatakan "implementasi ITask". Tentu saja, itu hanya berfungsi jika header grup tidak offscreen ..
Sedangkan: 'bool ITask.Execute ()' jelas dan tidak ambigu.
Pemisahan implementasi antarmuka yang jelas
Saya menganggap antarmuka sebagai lebih 'publik' daripada metode publik karena mereka dibuat untuk mengekspos hanya sedikit area permukaan dari tipe beton. Mereka mengurangi tipe menjadi kapabilitas, perilaku, seperangkat sifat, dll. Dan dalam implementasinya, saya pikir ini berguna untuk menjaga pemisahan ini.
Ketika saya melihat melalui kode kelas, ketika saya menemukan implementasi antarmuka eksplisit, otak saya beralih ke mode "kontrak kode". Seringkali implementasi ini hanya diteruskan ke metode lain, tetapi kadang-kadang mereka akan melakukan pengecekan status / param tambahan, konversi parameter yang masuk agar lebih cocok dengan persyaratan internal, atau bahkan terjemahan untuk tujuan pembuatan versi (yaitu beberapa generasi antarmuka semua berjalan menuju implementasi umum).
(Saya menyadari bahwa publik juga merupakan kontrak kode, tetapi antarmuka jauh lebih kuat, terutama dalam basis kode berbasis antarmuka di mana penggunaan langsung tipe konkret biasanya merupakan tanda kode internal saja.)
Terkait: Alasan 2 di atas oleh Jon .
Dan seterusnya
Plus kelebihan yang telah disebutkan dalam jawaban lain di sini:
Masalah
Tidak semua kesenangan dan kebahagiaan. Ada beberapa kasus di mana saya tetap dengan implisit:
- Jenis nilai, karena itu akan membutuhkan tinju dan perf yang lebih rendah. Ini bukan aturan ketat, dan tergantung pada antarmuka dan bagaimana itu dimaksudkan untuk digunakan. Sebanding? Implisit. IFattattable? Mungkin eksplisit.
- Antarmuka sistem trivial yang memiliki metode yang sering disebut langsung (seperti IDisposable.Dispose).
Juga, itu bisa menyebalkan untuk melakukan casting ketika Anda sebenarnya memiliki tipe beton dan ingin memanggil metode antarmuka eksplisit. Saya menangani ini dalam satu dari dua cara:
- Tambahkan publik dan minta metode antarmuka untuk menerapkannya. Biasanya terjadi dengan antarmuka yang lebih sederhana ketika bekerja secara internal.
- (Metode pilihan saya) Tambahkan
public IMyInterface I { get { return this; } }
(yang harus di sebaris) dan panggilan foo.I.InterfaceMethod()
. Jika banyak antarmuka yang membutuhkan kemampuan ini, perluas nama di luar saya (dalam pengalaman saya jarang ada yang membutuhkan ini).