"Ini" dalam parameter fungsi

88

Melihat beberapa contoh kode untuk HtmlHelpers, dan saya melihat deklarasi yang terlihat seperti:

public static string HelperName(this HtmlHelper htmlHelper, ...more regular params )

Saya tidak ingat melihat jenis konstruksi ini di tempat lain - dapatkah seseorang menjelaskan tujuan dari "ini"? Saya pikir dengan mendeklarasikan sesuatu yang statis publik berarti bahwa kelas tidak perlu dibuat instance-nya - jadi apa yang dimaksud dengan "ini" dalam kasus ini?

chris
sumber

Jawaban:

214

Ini adalah sintaks untuk mendeklarasikan metode ekstensi, fitur baru C # 3.0.

Metode penyuluhan adalah kode bagian, bagian penyusun "ajaib", di mana penyusun dengan bantuan Intellisense di Visual Studio membuatnya tampak bahwa metode penyuluhan Anda sebenarnya tersedia sebagai metode contoh pada objek yang dimaksud.

Izinkan saya memberi contoh.

Tidak ada metode pada kelas String yang bernama GobbleGobble, jadi mari buat metode ekstensi:

public static class StringExtensions
{
    public static void GobbleGobble(this string s)
    {
        Console.Out.WriteLine("Gobble Gobble, " + s);
    }
}

Nama kelas hanyalah konvensi penamaan saya, tidak perlu menamainya seperti itu, tetapi harus statis, seperti halnya metode.

Setelah mendeklarasikan metode di atas, Anda dapat, di Visual Studio, ketik ini:

String s = "Turkey Baster!";
s.

setelah titik tunggu intellisense, dan perhatikan ada metode GobbleGobble disana, lengkapi kodenya seperti ini:

String s = "Turkey Baster!";
s.GobbleGobble();

Penting : Kelas di mana metode ekstensi dideklarasikan harus tersedia untuk compiler dan prosesor intellisense agar intellisense dapat menampilkan metode tersebut. Jika Anda mengetik di GobbleGobble secara manual, dan menggunakan pintasan Ctrl+ ., itu tidak akan membantu Anda mendapatkan hak menggunakan arahan ke dalam file.

Perhatikan bahwa parameter metode telah menghilang. Kompiler diam-diam akan memindahkan bit-bit penting, yaitu:

String s = "Turkey Baster!";
s.GobbleGobble();
^     ^
|     +-- the compiler will find this in the StringExtensions class
|
+-- will be used as the first parameter to the method

Jadi, kode di atas akan diubah oleh compiler menjadi seperti ini:

String s = "Turkey Baster!";
StringExtensions.GobbleGobble(s);

Jadi pada waktu panggilan, tidak ada yang ajaib tentang itu, itu hanya panggilan ke metode statis.

Perhatikan bahwa jika metode ekstensi Anda mendeklarasikan lebih dari satu parameter, hanya parameter pertama yang mendukung thispengubah, dan sisanya harus ditetapkan sebagai bagian dari panggilan metode seperti biasa:

public static void GobbleGobble(this string value, string extra)
{                                            |              |
    ...                                      |              |
}                                            |              |
                                             |              |
+--------------------------------------------+              |
|                                                           |
v                                                           |
s.GobbleGobble("extra goes here");                          |
                        ^                                   |
                        |                                   |
                        +-----------------------------------+

Metode ekstensi ditambahkan sebagian karena Linq, di mana sintaks Linq dari C # akan mencari metode ekstensi yang diberi nama dengan tepat untuk objek yang sedang dimainkan, yang berarti Anda dapat "memperkenalkan" dukungan Linq ke dalam semua jenis kelas hanya dengan mendeklarasikan ekstensi yang tepat metode. Tentu saja, dukungan penuh Linq adalah pekerjaan yang berat, tetapi mungkin saja.

Selain itu, metode penyuluhan sendiri sangat berguna, jadi bacalah tentang itu.

Berikut beberapa tautan:

Lasse V. Karlsen
sumber
6
Saya pasti akan mulai menggunakan istilah "Sihir Gobble Gobble".
Chris
Youtube memutus lagi linknya, youtube.com/watch?v=Bz_heb9Rz2g , masih di @ 1: 00 dan seterusnya.
Lasse V. Karlsen
Sihir penyusun semacam ini menyulitkan untuk mempelajari suatu bahasa.
Don Dilanga
8

Setelah metode ekstensi, saya telah menggunakannya seperti orang gila .. berikut beberapa yang saya gunakan terus-menerus ..

public static T ChangeType<T>(this object obj)
{
  return (T)Convert.ChangeType(obj, typeof(T));
}

Bekerja seperti ini ..

int i = "123".ChangeType<int>();
bool valid = "bool".ChangeType<bool>();
int id = dataSet.Tables[0].Rows[0]["Id"].ChangeType<int>();

Ya, itu muncul di setiap objek, bisa mengganggu tetapi karena saya menggunakan ini untuk hampir semua tipe data, itu membantu untuk hanya melampirkan objek daripada menduplikasi untuk setiap tipe data yang mungkin.

public static string ToXml(this object serializableObject)
{
    var aMemStr = new MemoryStream();
    try
    {
        var serializer = new XmlSerializer(serializableObject.GetType());
        serializer.Serialize(new XmlTextWriter(aMemStr, null), serializableObject);
        return Encoding.UTF8.GetString(aMemStr.ToArray());
    }
    finally { if (aMemStr != null) { aMemStr.Dispose(); } }
}

string xml = dataSet.ToXml();

public static T ToObject<T>(this string xmlString)
{
    var aStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString));
    try { return (T)new XmlSerializer(typeof(T)).Deserialize(aStream); }
    finally { if (aStream != null) { aStream.Dispose(); aStream = null; } }
}

DataSet dataSet = xml.ToObject<DataSet>();
jaekie
sumber
6

Ini digunakan untuk metode ekstensi. Pada dasarnya Anda 'merekatkan' Helpername ke objek htmlHelper sehingga Anda dapat mengatakan:

new HtmlHelper().HelperName(...more regular params);
Henrik Gering
sumber
4

Itu akan menjadi Metode Ekstensi. Mereka memungkinkan Anda untuk "memperluas" kelas melalui metode statis yang berada di luar kelas asli.

Misalnya, Anda memiliki metode string bermanfaat yang Anda gunakan sepanjang waktu ...

public int CountAllAs(string orig)
{
    return orig.ToLowerInvariant().ToArray().Count(c => c == 'a');
}

Dan Anda menyebutnya ...

string allAs = "aaaA";
int count = CountAllAs(allAs);

Tidak terlalu buruk. Tetapi dengan sedikit perubahan, Anda bisa menjadikannya sebagai metode Ekstensi dan panggilannya akan menjadi sedikit lebih cantik:

public static int CountAllAs(this string orig)
{
    return orig.ToLowerInvariant().ToArray().Count(c => c == 'a');
}

Dan kemudian menyebutnya ...

string allAs = "aaaA";
int count = allAs.CountAllAs();
Justin Niessner
sumber
3

Metode Ekstensi ...

... adalah cara yang fantastis untuk memasukkan fungsionalitas seperti jika Anda menggunakan pola dekorator , tetapi tanpa rasa sakit dalam memfaktorkan ulang semua kode Anda, atau menggunakan nama yang berbeda dari jenis yang umum.

public static class Extensions
{
     public static string RemoveComma(this string value)
     {
         if (value == null) throw new ArgumentNullException("value");
        return value.Replace(",", "");
    }
}  

Jadi, Anda dapat menggunakan kode ini, di mana pun di aplikasi Anda.

Console.WriteLine(“Hello, My, Friend”.RemoveComma())

>> Hello My Friend

Jadi atribut perintah ini berarti jenis ekstensi yang akan "ditambahkan", dan membiarkan Anda bekerja dengan nilai seolah-olah itu diteruskan sebagai parameter.

Fraga
sumber