Saya penggemar metode ekstensi di C #, tetapi belum berhasil menambahkan metode ekstensi ke kelas statis, seperti Konsol.
Misalnya, jika saya ingin menambahkan ekstensi ke Konsol, yang disebut 'WriteBlueLine', sehingga saya dapat membuka:
Console.WriteBlueLine("This text is blue");
Saya mencoba ini dengan menambahkan metode statis publik lokal, dengan Konsol sebagai parameter 'ini' ... tetapi tidak ada dadu!
public static class Helpers {
public static void WriteBlueLine(this Console c, string text)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine(text);
Console.ResetColor();
}
}
Ini tidak menambahkan metode 'WriteBlueLine' ke Konsol ... apakah saya salah melakukannya? Atau meminta yang tidak mungkin?
c#
static
extension-methods
Leon Bambrick
sumber
sumber
Helpers.WriteBlueLine(null, "Hi");
:)Jawaban:
Tidak. Metode ekstensi memerlukan variabel instan (nilai) untuk objek. Namun Anda dapat, menulis pembungkus statis di sekitar
ConfigurationManager
antarmuka. Jika Anda menerapkan pembungkus, Anda tidak perlu metode ekstensi karena Anda bisa langsung menambahkan metode.sumber
Bisakah Anda menambahkan ekstensi statis ke kelas di C #? Tidak, tetapi Anda bisa melakukan ini:
Begini cara kerjanya. Meskipun Anda tidak dapat secara teknis menulis metode ekstensi statis, alih-alih kode ini mengeksploitasi celah dalam metode ekstensi. Celah itu adalah Anda dapat memanggil metode ekstensi pada objek nol tanpa mendapatkan pengecualian nol (kecuali Anda mengakses apa pun melalui @ ini).
Jadi, inilah cara Anda menggunakan ini:
Sekarang MENGAPA saya memilih memanggil konstruktor default sebagai contoh, dan DAN mengapa saya tidak mengembalikan T () baru dalam cuplikan kode pertama tanpa melakukan semua sampah Ekspresi? Baiklah hari ini hari keberuntunganmu karena kamu mendapatkan 2fer. Seperti diketahui oleh setiap pengembang .NET canggih, T () baru lambat karena menghasilkan panggilan ke System.Activator yang menggunakan refleksi untuk mendapatkan konstruktor default sebelum memanggilnya. Sialan kau, Microsoft! Namun kode saya memanggil konstruktor default objek secara langsung.
Ekstensi statis akan lebih baik dari ini, tetapi saat-saat putus asa membutuhkan tindakan putus asa.
sumber
XConsole
,ConsoleHelper
dan sebagainya.(null as DataSet).Create();
bisadefault(DataSet).Create();
.Itu tidak mungkin.
Dan ya saya pikir MS melakukan kesalahan di sini.
Keputusan mereka tidak masuk akal dan memaksa programmer untuk menulis (seperti dijelaskan di atas) kelas pembungkus yang tidak berguna.
Berikut ini adalah contoh yang baik: Mencoba untuk memperpanjang kelas pengujian Unit MS statis. Tegaskan: Saya ingin 1 lagi metode tegas
AreEqual(x1,x2)
.Satu-satunya cara untuk melakukan ini adalah dengan menunjuk ke kelas yang berbeda atau menulis pembungkus sekitar 100-an metode Assert yang berbeda. Mengapa!?
Jika keputusan telah dibuat untuk mengizinkan ekstensi instance, saya tidak melihat alasan logis untuk tidak mengizinkan ekstensi statis. Argumen tentang pustaka bagian tidak berdiri setelah instance dapat diperpanjang.
sumber
Assert.Throws
untuk menjawab stackoverflow.com/questions/113395/...Saya tersandung pada utas ini ketika mencoba menemukan jawaban untuk pertanyaan yang sama dengan yang OP miliki. Saya tidak menemukan jawaban yang saya inginkan tetapi akhirnya saya melakukan ini.
Dan saya menggunakannya seperti ini:
sumber
Mungkin Anda bisa menambahkan kelas statis dengan namespace kustom Anda dan nama kelas yang sama:
sumber
Pada C # 7 ini tidak didukung. Namun ada diskusi tentang mengintegrasikan sesuatu seperti itu di C # 8 dan proposal yang layak didukung .
sumber
Nggak. Definisi metode ekstensi memerlukan turunan jenis yang Anda perluas. Sangat disayangkan; Saya tidak yakin mengapa ini diperlukan ...
sumber
Adapun metode ekstensi, metode ekstensi itu sendiri statis; tetapi mereka dipanggil seolah-olah mereka adalah metode contoh. Karena kelas statis tidak instantiable, Anda tidak akan pernah memiliki instance dari kelas untuk memanggil metode ekstensi. Untuk alasan ini kompiler tidak mengijinkan metode ekstensi untuk didefinisikan untuk kelas statis.
Tn. Obnoxious menulis: "Seperti yang diketahui oleh pengembang .NET, T () baru lambat karena menghasilkan panggilan ke System.Activator yang menggunakan refleksi untuk mendapatkan konstruktor default sebelum memanggilnya".
New () dikompilasi dengan instruksi "newobj" IL jika jenisnya diketahui pada waktu kompilasi. Newobj mengambil konstruktor untuk doa langsung. Panggilan ke System.Activator.CreateInstance () kompilasi dengan instruksi "panggilan" IL untuk memanggil System.Activator.CreateInstance (). Baru () saat digunakan terhadap tipe generik akan menghasilkan panggilan ke System.Activator.CreateInstance (). Pos oleh Tn. Obnoxious tidak jelas tentang hal ini ... dan yah, menjengkelkan.
Kode ini:
menghasilkan IL ini:
sumber
Anda tidak dapat menambahkan metode statis ke suatu tipe. Anda hanya bisa menambahkan metode instance (pseudo-) ke instance dari suatu tipe.
Tujuan dari
this
pengubah adalah untuk memberitahu compiler C # untuk melewatkan instance di sisi kiri.
sebagai parameter pertama dari metode statis / ekstensi.Dalam hal menambahkan metode statis ke suatu tipe, tidak ada instance untuk melewatkan parameter pertama.
sumber
Saya mencoba melakukan ini dengan System.Environment ketika saya belajar metode ekstensi dan tidak berhasil. Alasannya, seperti yang disebutkan orang lain, karena metode ekstensi memerlukan turunan kelas.
sumber
Tidak mungkin untuk menulis metode ekstensi, namun dimungkinkan untuk meniru perilaku yang Anda minta.
Ini akan memungkinkan Anda untuk memanggil Console.WriteBlueLine (fooText) di kelas lain. Jika kelas lain menginginkan akses ke fungsi statis lain dari Konsol, mereka harus secara eksplisit dirujuk melalui namespace mereka.
Anda selalu dapat menambahkan semua metode ke kelas pengganti jika Anda ingin memiliki semuanya di satu tempat.
Jadi, Anda akan memiliki sesuatu seperti
Ini akan memberikan jenis perilaku yang Anda cari.
* Catatan Konsol harus ditambahkan melalui namespace yang Anda masukkan.
sumber
ya, dalam arti terbatas.
Ini berfungsi tetapi Konsol tidak karena itu statis.
Ini berfungsi karena selama itu tidak ada di namespace yang sama. Masalahnya adalah Anda harus menulis metode proxy statis untuk setiap metode yang dimiliki System.Console. Ini tidak selalu merupakan hal yang buruk karena Anda dapat menambahkan sesuatu seperti ini:
atau
Cara kerjanya adalah Anda menghubungkan sesuatu ke WriteLine standar. Itu bisa berupa jumlah baris atau filter kata yang buruk atau apa pun. Setiap kali Anda hanya menentukan Konsol di namespace Anda mengatakan WebProject1 dan mengimpor Sistem namespace, WebProject1.Console akan dipilih daripada System.Console sebagai default untuk kelas-kelas di namespace WebProject1. Jadi kode ini akan mengubah semua panggilan Console.WriteLine menjadi biru sejauh Anda tidak pernah menentukan System.Console.WriteLine.
sumber
Berikut ini ditolak sebagai hasil edit dari jawaban tvanfosson. Saya diminta untuk berkontribusi sebagai jawaban saya sendiri. Saya menggunakan sarannya dan menyelesaikan implementasi
ConfigurationManager
pembungkus. Pada prinsipnya saya hanya mengisi jawaban...
in tvanfosson.sumber
Anda dapat menggunakan gips pada null untuk membuatnya berfungsi.
Ekstensi:
Tipe kamu:
sumber
Anda BISA melakukan ini jika Anda bersedia "menikmatinya" sedikit dengan membuat variabel dari kelas statis dan menetapkannya ke nol. Namun, metode ini tidak akan tersedia untuk panggilan statis di kelas, jadi tidak yakin berapa banyak menggunakannya:
sumber