To jest pytanie dotyczące metod rozszerzenia C # i ich filozofii projektowania, więc myślę, że najlepszym sposobem na odpowiedź na to pytanie jest zacytowanie dokumentacji MSDN na temat metod rozszerzenia :
Metody rozszerzeń umożliwiają „dodawanie” metod do istniejących typów bez tworzenia nowego typu pochodnego, ponownej kompilacji lub innego modyfikowania oryginalnego typu. Metody rozszerzeń są specjalnym rodzajem metod statycznych, ale są wywoływane tak, jakby były metodami instancji typu rozszerzonego. W przypadku kodu klienta napisanego w C #, F # i Visual Basic nie ma widocznej różnicy między wywołaniem metody rozszerzenia a metodami, które są faktycznie zdefiniowane w typie.
…
Ogólnie zalecamy oszczędne wdrażanie metod rozszerzeń i tylko wtedy, gdy jest to konieczne. O ile to możliwe, kod klienta, który musi rozszerzyć istniejący typ, powinien to zrobić, tworząc nowy typ pochodzący z istniejącego typu. Aby uzyskać więcej informacji, zobacz Dziedziczenie.
Korzystając z metody rozszerzenia do rozszerzenia typu, którego kodu źródłowego nie można zmienić, istnieje ryzyko, że zmiana w implementacji typu spowoduje uszkodzenie metody rozszerzenia.
Jeśli implementujesz metody rozszerzenia dla danego typu, pamiętaj o następujących punktach:
- Metoda rozszerzenia nigdy nie zostanie wywołana, jeśli ma taki sam podpis jak metoda zdefiniowana w typie.
- Metody rozszerzeń są wprowadzane w zakres na poziomie przestrzeni nazw. Na przykład, jeśli masz wiele klas statycznych, które zawierają metody rozszerzeń w pojedynczej nazwanej przestrzeni nazw
Extensions
, wszystkie one zostaną objęte zakresem using Extensions;
dyrektywy.
Podsumowując, metody rozszerzeń służą do dodawania metod instancji do określonego typu, nawet jeśli programiści nie mogą tego zrobić bezpośrednio. A ponieważ metody instancji zawsze zastępują metody rozszerzeń, jeśli są obecne (jeśli są wywoływane przy użyciu składni metody instancji), należy to zrobić tylko wtedy, gdy nie można bezpośrednio dodać metody lub rozszerzyć klasy. *
Innymi słowy, metoda rozszerzenia powinna działać tak samo, jak metoda instancji, ponieważ może być w końcu metodą instancji stworzoną przez jakiegoś klienta. A ponieważ metoda instancji powinna rzucić, jeśli wywoływany jest obiekt null
, podobnie jak metoda rozszerzenia.
* Na marginesie, jest to dokładnie taka sytuacja, że projektanci z LINQ do czynienia: gdy C # 3.0 został wydany, były już miliony klientów, którzy używali System.Collections.IEnumerable
i System.Collections.Generic.IEnumerable<T>
, zarówno w swoich zbiorach i foreach
pętle. Klasy te zwrócone IEnumerator
przedmioty, które miał tylko dwie metody Current
i MoveNext
, więc dodanie dodatkowych wymaganych metod przykład, takie jak Count
, Any
itd byłoby złamanie tych milionów klientów. Tak więc, w celu dostarczenia tej funkcji (zwłaszcza, że to może być realizowane w warunkach Current
i MoveNext
ze względną łatwością), wydali go jako metod rozszerzeń, które mogą być stosowane do każdego obecnie istniejącychIEnumerable
wystąpienie i może być również zaimplementowane przez klasy w bardziej wydajny sposób. Gdyby projektanci C # zdecydowali się wydać LINQ pierwszego dnia, byłby on dostarczony jako metoda instancji IEnumerable
i prawdopodobnie zaprojektowaliby jakiś system zapewniający domyślne implementacje interfejsu tych metod.