İşlev parametresinde "bu"


88

HtmlHelpers için bazı kod örneklerine baktığımda şuna benzeyen bildirimler görüyorum:

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

Bu tür bir yapıyı başka bir yerde gördüğümü hatırlayamıyorum - birisi "bu" nun amacını açıklayabilir mi? Public static bir şeyi ilan etmenin sınıfın somutlaştırılmasına gerek olmadığı anlamına geldiğini düşündüm - bu durumda bu "bu" nedir?

Yanıtlar:


214

Bu, C # 3.0'ın yeni bir özelliği olan uzantı yöntemlerini bildirmek için kullanılan sözdizimidir.

Bir uzantı yöntemi, Visual Studio'daki intellisense yardımıyla derleyicinin, uzantı yönteminizin aslında söz konusu nesnede bir örnek yöntemi olarak mevcut olduğunu gösterdiği bölüm kod, parça derleyici "sihirli" dir.

Bir örnek vereyim.

String sınıfında GobbleGobble adlı bir yöntem yoktur, bu yüzden bir uzantı yöntemi oluşturalım:

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

Sınıf adı sadece benim adlandırma kuralımdır, onu böyle adlandırmak gerekli değildir, ancak yöntem gibi statik olması gerekir.

Yukarıdaki yöntemi bildirdikten sonra, Visual Studio'da şunu yazabilirsiniz:

String s = "Turkey Baster!";
s.

noktadan sonra, intellisense bekleyin ve orada bir GobbleGobble yöntemi olduğunu fark edin, kodu şu şekilde tamamlayın:

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

Önemli : Genişletme yönteminin bildirildiği sınıf, intellisense'in yöntemi göstermesi için derleyici ve intellisense işlemcisi tarafından kullanılabilir olmalıdır. GobbleGobble'ı manuel olarak yazarsanız ve Ctrl+ .kısayolunu kullanırsanız, dosyaya direktifleri kullanarak doğru şekilde girmenize yardımcı olmaz.

Yöntemin parametresinin kaybolduğuna dikkat edin. Derleyici, aşağıdaki önemli bitlerin etrafında sessizce hareket edecektir:

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

Böylece, yukarıdaki kod derleyici tarafından şuna dönüştürülecektir:

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

Yani görüşme zamanında, bunun sihirli bir yanı yok, sadece statik bir yönteme çağrı.

Uzantı yönteminiz birden fazla parametre bildirirse, yalnızca ilkinin thisdeğiştiriciyi desteklediğini ve geri kalanının yöntem çağrısının bir parçası olarak normal şekilde belirtilmesi gerektiğini unutmayın:

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

Uzantı yöntemleri kısmen Linq nedeniyle eklenmiştir; burada C # 'ın Linq sözdizimi, oyundaki nesneler için uygun şekilde adlandırılmış uzantı yöntemlerini arayacaktır, bu da Linq desteğini herhangi bir sınıf türüne yalnızca doğru uzantıyı bildirerek "tanıtabileceğiniz" anlamına gelir. yöntemler. Elbette, tam Linq desteği çok fazla iş gerektirir, ancak bu mümkündür.

Ayrıca, uzantı yöntemleri kendi başlarına gerçekten kullanışlıdır, bu yüzden okuyun.

İşte birkaç bağlantı:


6
Kesinlikle "Gobble Gobble Magic" terimini kullanmaya başlayacağım.
chris

Youtube bağlantıyı tekrar kırdı, youtube.com/watch?v=Bz_heb9Rz2g , hala @ 1: 00 ve sonrasında.
Lasse V. Karlsen

Bu tür derleyici büyüleri, bir dil öğrenmeyi zorlaştırır.
Don Dilanga

8

Uzatma yöntemlerinden sonra onları deli gibi kullanıyorum .. işte sürekli kullandığım bir kaç tane ..

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

Böyle çalışır ..

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

Evet, her nesnede ortaya çıkıyor, can sıkıcı olabilir, ancak bunu hemen hemen her veri türü için kullandığım için, mümkün olan her veri türü için kopyalamak yerine onu bir nesne eklemeye yardımcı oluyor.

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>();

6

Uzatma yöntemleri için kullanılır. Temel olarak Helpername'yi htmlHelper nesnesine 'yapıştırırsınız', böylece şunu söyleyebilirsiniz:

new HtmlHelper().HelperName(...more regular params);

4

Bu bir Genişletme Yöntemi olacaktır. Orijinal sınıfın dışında yaşayan statik yöntemler aracılığıyla bir sınıfı "genişletmenize" izin verir.

Örneğin, her zaman kullandığınız yararlı bir dize yönteminiz olduğunu varsayalım ...

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

Ve sen buna ...

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

Bu çok kötü değil. Ancak küçük bir değişiklikle, onu bir Uzantı yöntemi haline getirebilir ve çağrı biraz daha güzel olur:

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

Ve sonra ara ...

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

3

Uzantı Yöntemleri ...

... dekoratör kalıbını kullandığınız gibi işlevselliği dahil etmenin harika bir yoludur , ancak tüm kodunuzu yeniden düzenleme veya ortak bir türden farklı bir ad kullanma zahmeti olmadan.

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

Böylece bu kodu uygulamanızın her yerinde kullanabilirsiniz.

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

>> Hello My Friend

Dolayısıyla bu komut özelliği, uzantının "ekleneceği" tür anlamına gelir ve değerle parametre olarak aktarılmış gibi çalışmanıza izin verir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.