Earn More by Sharing What You Love
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Tim Corey
28m 27s
W programowaniu w C# metody są niezbędnymi elementami konstrukcyjnymi, które kapsułkują wielokrotnie używany kod i wykonują określone zadania. Mogą one przyjmować parametry, zwracać wartości i być przeciążane, by obsługiwać różne dane wejściowe. Bardziej zaawansowaną koncepcją są metody rozszerzające, które pozwalają programistom na dodawanie funkcjonalności do istniejących typów, w tym tych, nad którymi nie mają kontroli.
Film Tima Coreya 'How To Create Extension Methods in C#' jest doskonałym źródłem informacji. W tym przewodniku omówimy kilka tematów, które porusza Tim:
W C# metoda jest zdefiniowana w klasie. Ogólna składnia dla definicji metody obejmuje modyfikator dostępu, typ zwracany, nazwę metody i parametry.
public class SampleClass
{
public void SampleMethod()
{
// Method implementation
}
}Public Class SampleClass
Public Sub SampleMethod()
' Method implementation
End Sub
End ClassW przykładzie Tima Coreya o 4:05 definiuje on metodę w statycznej klasie, aby utworzyć metodę rozszerzającą. Metoda zdefiniowana jest przez PrintToConsole. Definicja obejmuje całą ogólną składnię, która wyraźnie wyjaśnia, jak zdefiniować metodę z praktycznym przykładem:
public static class Extensions
{
public static void PrintToConsole(this string message)
{
Console.WriteLine(message);
}
}Public Module Extensions
<System.Runtime.CompilerServices.Extension> _
Public Sub PrintToConsole(ByVal message As String)
Console.WriteLine(message)
End Sub
End Module'Wywołanie metody' mówi programowi, aby wykonał konkretną metodę zdefiniowaną gdzie indziej w kodzie, wykonując z góry zdefiniowaną akcję. Metody są wywoływane za pomocą instancji klasy lub bezpośrednio, jeśli są one metody statyczne. Dla metod rozszerzających wyglądają one, jakby były częścią typu, które rozszerzają. W wideo o 6:18 Tim pokazuje, jak wywołać metodę rozszerzającą z prymitywnym typem danych, tak jak w przypadku jego wbudowanych metod.
string demo = "This is a demo";
demo.PrintToConsole(); // Extension method callDim demo As String = "This is a demo"
demo.PrintToConsole() ' Extension method callParametry są określone w definicji metody i działają jako miejsca na wartości, które są przekazywane do metody. Możesz to zobaczyć tutaj po wywołaniu metody WriteLine, gdzie message jest parametrem.
public void DisplayMessage(string message)
{
Console.WriteLine(message);
}Public Sub DisplayMessage(message As String)
Console.WriteLine(message)
End SubPonownie, w przykładzie metody rozszerzenia, który dał Tim Corey o 4:05, message jest parametrem:
public static void PrintToConsole(this string message)
{
Console.WriteLine(message);
}<Extension()>
Public Sub PrintToConsole(ByVal message As String)
Console.WriteLine(message)
End SubArgumenty to rzeczywiste wartości przekazane do metody, gdy jest wywoływana.
DisplayMessage("Hello, World!"); // "Hello, World!" is the argumentDisplayMessage("Hello, World!") ' "Hello, World!" is the argumentKiedy Tim Corey wywołuje metodę o 6:20 używając składni z kropką z typem string, wartość tekstowa faktycznie jest przekazywana jako wartość do metody PrintToConsole:
string demo = "This is a demo";
demo.PrintToConsole(); // "This is a demo" is the argumentDim demo As String = "This is a demo"
demo.PrintToConsole() ' "This is a demo" is the argumentMetody mogą zwracać wartości za pomocą instrukcji return. Typ zwracany jest określony w sygnaturze metody.
public int Add(int a, int b)
{
return a + b;
}Public Function Add(a As Integer, b As Integer) As Integer
Return a + b
End FunctionCzookał metoda rozszerzająca w wideo Tima Coreya nie zwraca żadnej wartości (typ zwracany void), można jednak tworzyć metody rozszerzające ze zwracanymi wartościami. Typ zwracany w przykładzie Tima to void, co oznacza, że metoda nie zwraca żadnej wartości. Poniższy przykład pokazuje, jak zwrócić wartość:
public static int WordCount(this string str)
{
return str.Split(' ').Length;
}<Extension()>
Public Function WordCount(ByVal str As String) As Integer
Return str.Split(" "c).Length
End FunctionPrzeciążanie metod pozwala na posiadanie wielu metod o tej samej nazwie, ale różnych parametrach. Może być to przydatne przy tworzeniu elastycznych i intuicyjnych API.
public void Display(string message)
{
Console.WriteLine(message);
}
public void Display(int number)
{
Console.WriteLine(number);
}Public Sub Display(message As String)
Console.WriteLine(message)
End Sub
Public Sub Display(number As Integer)
Console.WriteLine(number)
End SubTim Corey krótko omawia tworzenie wielu metod dla różnych scenariuszy logowania o 11:24, co może być widziane jako przykład przeciążania metod w szerszym znaczeniu. Metoda logowania istnieje dwukrotnie, jedna z jednym parametrem, a druga z dwoma parametrami. Druga metoda logowania o 11:39 jest przeciążoną wersją metody logowania, nadając jej wiele funkcji pod tą samą nazwą.
Metody rozszerzające pozwalają na dodawanie nowych metod do istniejących typów, bez potrzeby ich modyfikacji lub rekompilacji. Choć są wywoływane tak, jakby były metodami instancji, metody rozszerzające są definiowane jako metody statyczne.
W poprzedniej sekcji 'Definiowanie i Wywoływanie Metod' podkreśliliśmy, jak Tim Corey stworzył metodę rozszerzającą w oddzielnej klasie statycznej i zdefiniował w niej metodę statyczną do użycia jako metoda rozszerzająca. Oto kilka kluczowych punktów, które podkreśla Tim Corey:
this, określając typ do rozszerzenia (4:58)public static class Extensions
{
public static void PrintToConsole(this string message)
{
Console.WriteLine(message);
}
}Public Module Extensions
<System.Runtime.CompilerServices.Extension> _
Public Sub PrintToConsole(ByVal message As String)
Console.WriteLine(message)
End Sub
End ModuleNastępnie Tim pokazuje, jak wywołać metodę rozszerzającą na tej zmiennej typu string:
demo.PrintToConsole();demo.PrintToConsole()Kiedy wprowadzasz demo i zaczynasz pisać Print, IntelliSense sugeruje metodę PrintToConsole. To jest nowa metoda dodana do typu string.
Tim wyjaśnia, dlaczego możesz wywołać demo.PrintToConsole():
demo jest typu string.string został rozszerzony o nową metodę PrintToConsole.Chociaż wydaje się, że żadne parametry nie są przekazywane do metody PrintToConsole, Tim wskazuje na ukryte przekazywanie parametru - ciąg demo jest przekazywany jako pierwszy parametr do metody rozszerzenia.
Tim podkreśla, że metody rozszerzające mają jeden parametr mniej w wywołaniu niż w definicji. To dlatego, że pierwszy parametr (typ, który jest rozszerzany) jest domyślny.
Tutaj, this string message oznacza, że metoda rozszerza typ string, a message jest ukrytym parametrem:
public static void PrintToConsole(this string message)<Extension()>
Public Sub PrintToConsole(ByVal message As String)Na koniec, kiedy metoda PrintToConsole jest wywoływana, wypisuje ciąg na konsolę:
Console.WriteLine(message);Console.WriteLine(message)Więc, wywołanie demo.PrintToConsole() wypisuje "This is a demo" na konsolę.
Tim Corey wyjaśnia, że metody rozszerzające mogą rozszerzać dowolny typ, nawet klasy stron trzecich, których nie można modyfikować bezpośrednio. Na przykład, spójrzmy na klasę SimpleLogger o 11:09.
Tutaj, Tim używa hipotetycznej klasy zewnętrznej SimpleLogger, która zapisuje wiadomości na konsolę (11:09). Klasa ma dwie metody:
public class SimpleLogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
public void Log(string message, string messageType)
{
Console.WriteLine($"{messageType}: {message}");
}
}Public Class SimpleLogger
Public Sub Log(message As String)
Console.WriteLine(message)
End Sub
Public Sub Log(message As String, messageType As String)
Console.WriteLine($"{messageType}: {message}")
End Sub
End ClassTe metody nie są idealne, ponieważ typ wiadomości to prosty string, co może prowadzić do niespójności. Tim sugeruje stworzenie metod rozszerzających, aby poprawić klasę.
Używanie metod rozszerzających zapewnia spójność w kodzie, zawsze używając tych samych typów wiadomości i formatowania. Tutaj (12:40), Tim tworzy statyczną klasę ExtendSimpleLogger:
public static class ExtendSimpleLogger
{
public static void LogError(this SimpleLogger logger, string message)
{
logger.Log(message, "Error");
}
public static void LogWarning(this SimpleLogger logger, string message)
{
logger.Log(message, "Warning");
}
}Public Module ExtendSimpleLogger
<System.Runtime.CompilerServices.Extension>
Public Sub LogError(ByVal logger As SimpleLogger, ByVal message As String)
logger.Log(message, "Error")
End Sub
<System.Runtime.CompilerServices.Extension>
Public Sub LogWarning(ByVal logger As SimpleLogger, ByVal message As String)
logger.Log(message, "Warning")
End Sub
End ModuleDzięki temu (14:02) jest teraz w stanie wywołać metody rozszerzenia na instancji SimpleLogger:
SimpleLogger logger = new SimpleLogger();
logger.LogError("This is an error");
logger.LogWarning("This is a warning");Dim logger As New SimpleLogger()
logger.LogError("This is an error")
logger.LogWarning("This is a warning")To zapewnia, że typy wiadomości są zawsze 'Error' i 'Warning'.
Tim dodaje funkcjonalność do ustawiania koloru tekstu konsoli dla wiadomości o błędach, zapewniając, że się wyróżniają:
public static void LogError(this SimpleLogger logger, string message)
{
var defaultColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
logger.Log(message, "Error");
Console.ForegroundColor = defaultColor;
}<Extension()>
Public Sub LogError(ByVal logger As SimpleLogger, ByVal message As String)
Dim defaultColor = Console.ForegroundColor
Console.ForegroundColor = ConsoleColor.Red
logger.Log(message, "Error")
Console.ForegroundColor = defaultColor
End SubTim porównuje to podejście do bezpośredniego wywoływania oryginalnych metod Log, co mogłoby prowadzić do niespójności:
logger.Log("Test error", "Error");
logger.Log("Another error", "ERROR");logger.Log("Test error", "Error")
logger.Log("Another error", "ERROR")Podejście to jest podatne na literówki i niespójne formatowanie.
Tim demonstruje, jak metody rozszerzające mogą być łączone, aby kod był bardziej czytelny:
public static void LogInfo(this SimpleLogger logger, string message)
{
logger.Log(message, "Info");
}
public static void SaveToDatabase(this SimpleLogger logger)
{
// Simulate saving to a database
}Public Sub LogInfo(ByVal logger As SimpleLogger, ByVal message As String)
logger.Log(message, "Info")
End Sub
Public Sub SaveToDatabase(ByVal logger As SimpleLogger)
' Simulate saving to a database
End SubTeraz możesz łączyć te metody:
logger.LogInfo("Information").SaveToDatabase();logger.LogInfo("Information").SaveToDatabase()To sprawia, że kod jest bardziej czytelny i intuicyjny w porównaniu do zagnieżdżonych wywołań metod:
SaveToDatabase(LogInfo(logger, "Information"));SaveToDatabase(LogInfo(logger, "Information"))Korzystając z notacji kropkowej i łączenia, intencja kodu jest bardziej przejrzysta i mniej zagnieżdżona.
O 20:13 Tim Corey wyjaśnia, że metody rozszerzające są idealne do dodawania funkcjonalności do klas, które nie są twoją własnością, takich jak biblioteki stron trzecich. Pozwala to na ulepszenia bez modyfikacji oryginalnego kodu.
Corey również podkreśla użycie metod rozszerzających do wprowadzenia zależności bez ich bezpośredniego sprzęgania z klasą. Na przykład, dodanie funkcjonalności zapisywania do bazy danych do klasy Person bez osadzania logiki bazy danych.
Metody rozszerzające mogą również dotyczyć interfejsów, jak wyjaśniono od 21:30, umożliwiając wielu klasom implementującym interfejs dzielenie tej samej funkcjonalności. To promuje ponowne wykorzystanie kodu i uproszczenie.
O 23:03 Tim Corey doradza, aby nie nadużywać metod rozszerzających, zwłaszcza z typami prymitywnymi lub dostarczanymi przez Microsoft, aby uniknąć zagracenia i złożoności. Używaj ich oszczędnie i tylko wtedy, gdy oferują wyraźne korzyści.
W sekcji między 24:54-25:40 Tim podkreśla przestrzeganie zasady otwartości/zamkniętości poprzez użycie metod rozszerzających do dodawania nowej funkcjonalności bez modyfikowania istniejącego, stabilnego kodu, co zmniejsza ryzyko wprowadzania błędów.
Organizuj metody rozszerzające, grupując je logicznie i umieszczając w oddzielnych przestrzeniach nazw, aby uniknąć konfliktów nazw i ułatwić utrzymanie i debugowanie.
I proszę bardzo – teraz rozumiesz podstawy definiowania i wywoływania metod, obsługi parametrów i wartości zwracanych oraz wykorzystywania przeciążania metod. Dzięki temu możesz budować solidne i elastyczne aplikacje w C#.
Metody rozszerzające, jak wyjaśnia Tim Corey, oferują potężny sposób na ulepszanie istniejących typów i czynią twój kod bardziej czytelnym i utrzymywalnym. Dla bardziej szczegółowych informacji i praktycznych przykładów możesz obejrzeć pełne wideo Tima Coreya na temat How To Create Extension Methods in C#.
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!
Join our newsletter, you’ll get exclusive access on article updates. We value your privacy