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.IEnumerablei System.Collections.Generic.IEnumerable<T>, zarówno w swoich zbiorach i foreachpętle. Klasy te zwrócone IEnumeratorprzedmioty, które miał tylko dwie metody Currenti MoveNext, więc dodanie dodatkowych wymaganych metod przykład, takie jak Count, Anyitd 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 Currenti MoveNextze względną łatwością), wydali go jako metod rozszerzeń, które mogą być stosowane do każdego obecnie istniejącychIEnumerablewystą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 IEnumerablei prawdopodobnie zaprojektowaliby jakiś system zapewniający domyślne implementacje interfejsu tych metod.