Problem, który chcemy rozwiązać
Załóżmy, że mamy do rozwiązania prosty problem. Wyświetlamy tabelę z produktami, między innymi z polem typu string - opis. Ten opis powiedzmy, że jest przechowywany w bazie danych i może mieć maksymalną wielkość 300 znaków. Jednak my w tabeli chcemy wyświetlić tylko 20 pierwszych znaków. Jeżeli dany opis ma 20 znaków lub mniej, to wtedy wyświetlamy cały opis, jednak jeżeli opis produktu ma więcej niż 17 znaków, to wtedy wyświetlamy 17 pierwszych znaków i dodajemy przyrostek "...". Dzięki temu opis może mieć maksymalnie 20 znaków. Fajnie, jeżeli to rozwiązanie będzie uniwersalne i będzie można go użyć w wielu miejscach, w różnych klasach i projektach. Jak można zaimplementować takie rozwiązanie?
Rozwiązanie 1 - Dodanie zwykłej metody statycznej do projektu
Wydaje mi się, że pierwsze najbardziej intuicyjne rozwiązanie, to dodanie nowej metody statycznej, która jako parametr będzie przyjmować string'a, czyli opis, który następnie zmodyfikuje, jeżeli będzie taka potrzeba i zwróci pierwszych 20 znaków. Tak może wyglądać przykładowa implementacja wraz z wywołaniem:
namespace App
{
class Program
{
static void Main(string[] args)
{
var description = "12345678901234567890X";
var shortDescription = StringMethods.GetTheFirstNCharacters(description, 20);
Console.WriteLine(shortDescription);
///12345678901234567...
}
}
public static class StringMethods
{
public static string GetTheFirstNCharacters(string val, int maxNumberOfCharacters)
{
if (string.IsNullOrWhiteSpace(val))
return string.Empty;
if (val.Length <= maxNumberOfCharacters)
return val;
return val.Substring(0, maxNumberOfCharacters - 3) + "...";
}
}
}
Jak widzisz, rozwiązanie to spełnia wszystkie założenia, ale czy jest ono idealne? Nie, myślę, że można to rozwiązanie napisać lepiej, dzięki metodom rozszerzającym. Jak w takim razie, powinno wyglądać to rozwiązanie?
Rozwiązanie 2 - Wykorzystanie metody rozszerzającej
Drugie rozwiązanie już może nie być dla wszystkich takie intuicyjne, ale myślę, że w tym przypadku będzie dużo lepsze. To znaczy, możemy skorzystać właśnie z tytułowych metod rozszerzających, dzięki czemu rozszerzymy klasę string o nową metodę, którą będziemy mogli używać w naszych aplikacjach. Także dzięki metodom rozszerzającym, możemy rozszerzyć dowolną klasę bez używania dziedziczenia.
namespace App
{
class Program
{
static void Main(string[] args)
{
var description = "12345678901234567890X";
var shortDescription = description.GetTheFirstNCharacters(20);
Console.WriteLine(shortDescription);
//12345678901234567...
}
}
public static class StringExtensions
{
public static string GetTheFirstNCharacters(this string val, int maxNumberOfCharacters)
{
if (string.IsNullOrWhiteSpace(val))
return string.Empty;
if (val.Length <= maxNumberOfCharacters)
return val;
return val.Substring(0, maxNumberOfCharacters - 3) + "...";
}
}
}
Jeżeli chodzi o logikę, to tutaj nie ma żadnych zmian, ale w tym przypadku użyłem metody rozszerzającej, dzięki czemu klasa string została rozszerzona o nową metodę. Możesz używać metody GetTheFirstNCharacters jak zwykłej metody klasy string. Jest ta metoda również podpowiadana przez intellisense po wpisaniu kropki po nazwie zmiennej. Wydaje mi się, że taki zapis jest dużo bardziej czytelny i uniwersalny. Nie musisz tutaj wywoływać żadnych statycznych metod z innych klas, tylko wywołujesz metodę rozszerzającą jak każdą inną metodę klasy string. Ponadto możesz takie metody rozszerzające wyodrębnić do osobnego projektu i używać ich w innych swoich aplikacjach, jeżeli będzie taka potrzeba.
Jak pisać metody rozszerzające?
Aby metodą była metodą rozszerzającą, to musi spełniać kilka warunków:
- Musi zostać zaimplementowana w klasie statycznej
- Metoda rozszerzająca musi być statyczna
- Pierwszy parametr metody rozszerzającej musi zostać poprzedzony słowem kluczowym this, przed nazwą klasy, którą rozszerza
Jeżeli intellisense nie będzie podpowiadał składni, to znaczy nie będzie pokazywał Twojej metody, to prawdopodobnie (jeżeli dobrze zdefiniowałeś metodę rozszerzającą) metoda została napisana w innym namespace'ie, dlatego również musisz dodać odpowiedniego using'a w tym pliku.
Ja w swoich projektach często korzystam z takich metod rozszerzających. Zawsze trzymam się takiej konwencji, że dana metoda rozszerzająca znajduje się w klasie o nazwie: rozszerzany typ + przyrostek Extensions. To znaczy dla string'a, będzie to klasa o nazwie StringExtensions tak jak w powyższym przykładzie. Takie metody oraz odpowiednia struktura projektu zwiększa czytelność kodu.
Przykłady metod rozszerzających
W c# często spotykasz się z różnymi metodami rozszerzającymi. Często z nich korzystasz, a możesz nawet o tym nie wiedzieć. Przykładem takich metod są metody LINQ. To znaczy na przykład obliczanie sumy kolekcji IEnumerable:
var myNumbers = new List<int> { 1, 2, 3 };
myNumbers.Sum();
A tak wygląda sygnatura metody Sum:
public static int Sum(this IEnumerable<int> source);
Jak widzisz, jest to metoda rozszerzająca klasę IEnumerable.
PODSUMOWANIE:
Jak widzisz, metody rozszerzające mogą mieć różne zastosowanie, ja w swoich projektach często z nich korzystam, w celu poprawienia czytelności kodu. Dzięki nim możesz w łatwy sposób rozszerzyć przede wszystkim kod, do którego nie masz dostępu. Jeżeli chcesz zostać programistą .NET, to znajomość tego tematu również może Ci się przydać na rozmowach kwalifikacyjnych. Rekruterzy lubią poruszyć temat metod rozszerzających, jeżeli interesują Cię takie zagadnienia, to jakiś czas temu przygotowałem specjalny dokument PDF, w którym znajdziesz pytania i odpowiedzi na 10 najczęstszych pytań z rozmów kwalifikacyjnych (+bonus) na stanowisko młodszego programisty .NET (🔥 tutaj dokument PDF). Jeżeli masz jakieś pytania co do tego tematu, to napisz, proszę komentarz poniżej lub napisz do mnie e-mail'a 🙂
Poprzedni artykuł - Logowanie Danych Do Pliku w C# Za Pomocą Biblioteki NLog.
Następny artykuł - Za Stary Na Programowanie? Czy Można Zostać Programistą Po 30-stce?