Ada saat-saat di mana saya ingin menimpa metode di kelas dengan metode ekstensi. Apakah ada cara untuk melakukan itu di C #?
Sebagai contoh:
public static class StringExtension
{
public static int GetHashCode(this string inStr)
{
return MyHash(inStr);
}
}
Kasus di mana saya ingin melakukan ini adalah untuk dapat menyimpan hash string ke dalam database dan memiliki nilai yang sama digunakan oleh semua kelas yang menggunakan hash kelas string (yaitu Kamus, dll.) Sejak Algoritme hashing. Net bawaan tidak dijamin kompatibel dari satu versi Framework ke versi berikutnya, saya ingin menggantinya dengan versi saya sendiri.
Ada kasus lain yang saya temui di mana saya ingin mengganti metode kelas dengan metode ekstensi juga sehingga tidak hanya spesifik untuk kelas string atau metode GetHashCode.
Saya tahu saya bisa melakukan ini dengan subclassing dari kelas yang ada tetapi akan berguna untuk dapat melakukannya dengan ekstensi dalam banyak kasus.
sumber
Jawaban:
Tidak; metode ekstensi tidak pernah mengambil prioritas di atas metode instance dengan tanda tangan yang sesuai, dan tidak pernah berpartisipasi dalam polimorfisme (
GetHashCode
adalahvirtual
metode).sumber
.ToString()
dalam array. Ini jelas merupakan fitur yang dibutuhkan.namespace System { public static class guilty { public static string ToLower(this string s) { return s.ToUpper() + " I'm Malicious"; } } }
Jika metode tersebut memiliki tanda tangan yang berbeda, maka itu bisa dilakukan - jadi dalam kasus Anda: tidak.
Tetapi jika tidak, Anda perlu menggunakan warisan untuk melakukan apa yang Anda cari.
sumber
Sejauh yang saya tahu jawabannya adalah tidak, karena metode ekstensi bukanlah sebuah instance. Ini lebih seperti fasilitas intellisense bagi saya yang memungkinkan Anda memanggil metode statis menggunakan instance kelas. Saya rasa solusi untuk masalah Anda dapat berupa interseptor yang mencegat pelaksanaan metode tertentu (mis. GetHashCode ()) dan melakukan hal lain.Untuk menggunakan pencegat seperti itu (seperti yang disediakan Proyek Kastil) semua objek harus instansiated menggunakan pabrik objek (atau wadah IoC di Castle) sehingga antarmuka mereka dapat dicegat melalui proxy dinamis yang dihasilkan dalam runtime. (Caslte juga memungkinkan Anda mencegat anggota virtual kelas)
sumber
Saya telah menemukan cara untuk memanggil metode ekstensi dengan tanda tangan yang sama sebagai metode kelas, namun tampaknya tidak terlalu elegan. Saat bermain-main dengan metode ekstensi, saya melihat beberapa perilaku yang tidak terdokumentasi. Kode sampel:
Apa yang saya perhatikan adalah jika saya memanggil metode kedua dari dalam metode ekstensi, itu akan memanggil metode ekstensi yang cocok dengan tanda tangan bahkan jika ada metode kelas yang juga cocok dengan tanda tangan. Misalnya dalam kode di atas, ketika saya memanggil ExtFunc (), yang pada gilirannya memanggil ele.GetDesc (), saya mendapatkan string kembali "Extension GetDesc" alih-alih string "Base GetDesc" yang kita harapkan.
Menguji kode:
Hal ini memungkinkan Anda untuk bolak-balik antara metode kelas dan metode ekstensi sesuka hati, tetapi memerlukan penambahan metode "pass-through" duplikat untuk membawa Anda ke "cakupan" yang Anda inginkan. Saya menyebutnya ruang lingkup di sini karena kurangnya kata yang lebih baik. Mudah-mudahan seseorang bisa memberi tahu saya apa sebenarnya namanya.
Anda mungkin telah menebak dengan nama metode "pass-through" saya bahwa saya juga bermain-main dengan gagasan meneruskan delegasi kepada mereka dengan harapan bahwa satu atau dua metode dapat bertindak sebagai pass-through untuk beberapa metode dengan tanda tangan yang sama. Sayangnya itu tidak terjadi setelah delegasi diekstrak, ia selalu memilih metode kelas daripada metode ekstensi bahkan dari dalam metode ekstensi lain. "Cakupan" tidak lagi penting. Saya belum banyak menggunakan delegasi Action dan Func, jadi mungkin seseorang yang lebih berpengalaman dapat memahami bagian itu.
sumber