Extension Methods – metody rozszerzające, które pozwalają na wykorzystanie raz napisanego kodu w wielu miejscach bez naginania zasady DRY (Don’t Repeat Yourself). Metoda taka musi być statyczna i musi być zarejestrowana w statycznej klasie. W ten sposób możemy bardzo łatwo rozszerzać operacje na podstawowych typach, jak również rozszerzać funkcjonalność typów pochodzących z zewnętrznych bibliotek. Załóżmy prosty przykład, mamy 2 klasy, które nie są ze sobą w żaden sposób powiązane, nie mają wspólnej klasy bazowej. W każdej z nich chcemy sprawdzić, czy nasz string zawiera pusty znak. Możemy tu zaciągnąć do pracy właśnie metodę rozszerzającą:
public static class StringHelper { public static bool ContainsWhiteSpacesExtensionMethod(this string s) { return s.Contains(" "); } }
Pozostaje pytanie – dlaczego w deklaracji metody, przy argumencie pojawia się słowo kluczowe this? Załóżmy, że wyżej stworzona metoda jest klasyczną metodą statyczną ze statycznej klasy:
public static class StringHelper { public static bool ContainsWhiteSpacesStaticMethod(string s) { return s.Contains(" "); } }
Zobaczmy, jaka jest różnica pomiędzy wywołaniem metody rozszerzającej, a wywołaniem zwykłej metody statycznej:
class Program { static void Main(string[] args) { string helloWorld = "Hello World!"; // call extension method if (helloWorld.ContainsWhiteSpacesExtensionMethod()) { Console.WriteLine("Success!"); } // call normal static method if (StringHelper.ContainsWhiteSpacesStaticMethod(helloWorld)) { Console.WriteLine("Success!"); } Console.ReadKey(); }
Jak widać, dużo prostsze jest użycie metody rozszerzającej, bezpośrednio na obiekcie niż wywołanie metody na statycznej klasie i podanie jako argument stringa.
Bardzo ważnym punktem, o którym nie można zapomnieć w przypadku extension methods jest to, że w momencie, gdy wywołamy taką metodę na pustym obiekcie, metoda nie rzuci wyjątkiem NullReferenceException. Należy o tym pamiętać!
“Metoda taka musi być statyczna i musi być zarejestrowana w statycznej klasie.” – zapomniałeś dodać jeszcze dwóch ograniczeń. Metody nie mogą być generyczne i dodatkowo klasy statyczne z tymi metodami nie mogą być zagnieżdżone.
W jaki sposób rozumiesz generyczne? Krótki przykład:
public static T Get<T>(this T[] param)
{
return param != null ? param.FirstOrDefault() : default(T);
}
Oczywiście masz rację 😉 – chodziło mi o klasę, nie metodę. Komentarz pisałem na szybko i stąd pomyłka.
PS. Usuń komentarz poniżej 🙂
Usunięty 🙂
Warto dodać, że w momencie kompilacji metoda taka przekształcana jest po prostu w inline method. Suma sumarum kod który piszemy to tylko syntatic sugar piękne dla naszych oczu 😉
Zgadza się 🙂 Natomiast wg mnie to gra warta świeczki, bo użycie takiej metody rozszerzającej wygląda dużo lepiej i jest wygodniejsze w użyciu.