To jest składnia deklarowania metod rozszerzenia, nowa funkcja języka C # 3.0.
Metodą rozszerzającą jest kod częściowy, kompilator częściowy „magiczny”, w którym kompilator z pomocą funkcji Intellisense w programie Visual Studio sprawia, że wygląda na to, że metoda rozszerzenia jest faktycznie dostępna jako metoda instancji danego obiektu.
Podam przykład.
W klasie String nie ma metody o nazwie GobbleGobble, więc stwórzmy metodę rozszerzającą:
public static class StringExtensions
{
public static void GobbleGobble(this string s)
{
Console.Out.WriteLine("Gobble Gobble, " + s);
}
}
Nazwa klasy jest po prostu moją konwencją nazewnictwa, nie jest konieczne nazywanie jej w ten sposób, ale musi być statyczna, podobnie jak metoda.
Po zadeklarowaniu powyższej metody możesz w programie Visual Studio wpisać:
String s = "Turkey Baster!";
s.
po kropce poczekaj na intelisense i zauważ, że jest tam metoda GobbleGobble, uzupełnij kod w ten sposób:
String s = "Turkey Baster!";
s.GobbleGobble();
Ważne : Klasa, w której zadeklarowano metodę rozszerzającą, musi być dostępna dla kompilatora i procesora Intellisense, aby funkcja Intellisense mogła wyświetlić metodę. Jeśli wpiszesz GobbleGobble ręcznie i użyj rozszerzeniaCtrl. skrótu + , nie pomoże ci to we wprowadzeniu odpowiednich dyrektyw do pliku.
Zwróć uwagę, że parametr metody zniknął. Kompilator po cichu porusza się po ważnych bitach, którymi są:
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
Zatem powyższy kod zostanie przekształcony przez kompilator do tego:
String s = "Turkey Baster!";
StringExtensions.GobbleGobble(s);
Więc w czasie rozmowy nie ma w tym nic magicznego, to po prostu wywołanie metody statycznej.
Zauważ, że jeśli twoja metoda rozszerzająca deklaruje więcej niż jeden parametr, tylko pierwszy obsługuje this
modyfikator, a reszta musi być określona jako część wywołania metody normalnie:
public static void GobbleGobble(this string value, string extra)
{ | |
... | |
} | |
| |
+--------------------------------------------+ |
| |
v |
s.GobbleGobble("extra goes here"); |
^ |
| |
+-----------------------------------+
Metody rozszerzające zostały dodane częściowo ze względu na Linq, gdzie składnia Linq języka C # będzie szukała odpowiednio nazwanych metod rozszerzających dla obiektów w grze, co oznacza, że można „wprowadzić” obsługę Linq do dowolnego typu klasy, po prostu zadeklarując odpowiednie rozszerzenie metody. Oczywiście pełne wsparcie Linq to dużo pracy, ale jest możliwe.
Również same metody rozszerzające są bardzo przydatne, więc przeczytaj je.
Oto kilka linków:
Po metodach rozszerzających używam ich jak szalone ... oto kilka, których używam stale ..
public static T ChangeType<T>(this object obj) { return (T)Convert.ChangeType(obj, typeof(T)); }
Działa w ten sposób ...
int i = "123".ChangeType<int>(); bool valid = "bool".ChangeType<bool>(); int id = dataSet.Tables[0].Rows[0]["Id"].ChangeType<int>();
Tak, pojawia się na każdym obiekcie, może być denerwujące, ale ponieważ używam tego dla prawie każdego typu danych, pomaga to po prostu dołączyć obiekt, a nie powielać go dla każdego możliwego typu danych.
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>();
źródło
Służy do metod rozszerzania. Zasadniczo „przyklejasz” nazwę pomocnika do obiektu htmlHelper, aby móc powiedzieć:
new HtmlHelper().HelperName(...more regular params);
źródło
To byłaby metoda rozszerzenia. Umożliwiają one „rozszerzenie” klasy za pomocą metod statycznych, które istnieją poza klasą oryginalną.
Załóżmy na przykład, że masz przydatną metodę ciągów, której używasz przez cały czas ...
public int CountAllAs(string orig) { return orig.ToLowerInvariant().ToArray().Count(c => c == 'a'); }
I nazywasz to ...
string allAs = "aaaA"; int count = CountAllAs(allAs);
Nie aż tak źle. Ale z niewielką zmianą możesz uczynić ją metodą rozszerzenia, a wywołanie byłoby trochę ładniejsze:
public static int CountAllAs(this string orig) { return orig.ToLowerInvariant().ToArray().Count(c => c == 'a'); }
A potem nazwij to ...
string allAs = "aaaA"; int count = allAs.CountAllAs();
źródło
Metody rozszerzeń ...
... to fantastyczny sposób na włączenie funkcjonalności, takiej jak w przypadku używania wzorca dekoratora , ale bez bólu związanego z refaktoryzacją całego kodu lub używania innej nazwy wspólnego typu.
public static class Extensions { public static string RemoveComma(this string value) { if (value == null) throw new ArgumentNullException("value"); return value.Replace(",", ""); } }
Możesz więc używać tego kodu w dowolnym miejscu aplikacji.
Zatem atrybut this command oznacza typ, w jakim rozszerzenie zostanie „dodane”, i pozwala pracować z wartością tak, jakby była przekazywana jako parametr.
źródło