Esta es una pregunta sobre los métodos de extensión de C # y su filosofía de diseño, por lo que creo que la mejor forma de responder esta pregunta es citar a Documentación de MSDN sobre el propósito de los métodos de extensión :
Los métodos de extensión le permiten "agregar" métodos a los tipos existentes sin crear un nuevo tipo derivado, recompilar o modificar el tipo original. Los métodos de extensión son un tipo especial de método estático, pero se llaman como si fueran métodos de instancia en el tipo extendido. Para el código de cliente escrito en C #, F # y Visual Basic, no hay una diferencia aparente entre llamar a un método de extensión y los métodos que realmente están definidos en un tipo.
...
En general, recomendamos que implemente métodos de extensión con moderación y solo cuando sea necesario. Siempre que sea posible, el código de cliente que debe extender un tipo existente debe hacerlo creando un nuevo tipo derivado del tipo existente. Para más información, ver Herencia.
Cuando usa un método de extensión para extender un tipo cuyo código fuente no puede cambiar, corre el riesgo de que un cambio en la implementación del tipo provoque que su método de extensión se rompa.
Si implementa métodos de extensión para un tipo determinado, recuerde los siguientes puntos:
- Nunca se llamará a un método de extensión si tiene la misma firma que un método definido en el tipo.
- Los métodos de extensión están dentro del alcance en el nivel del espacio de nombres. Por ejemplo, si tiene varias clases estáticas que contienen métodos de extensión en un único espacio de nombres llamado
Extensions
, la directiva using Extensions;
las pondrá en alcance.
Para resumir, los métodos de extensión están diseñados para agregar métodos de instancia a un tipo particular, incluso cuando los desarrolladores no pueden hacerlo directamente. Y debido a que los métodos de instancia siempre anularán los métodos de extensión si están presentes (si se los llama utilizando la sintaxis del método de instancia), esto debería solo si no puede agregar un método directamente o ampliar la clase . *
En otras palabras, un método de extensión debe actuar como lo haría un método de instancia, ya que algún cliente puede convertirlo en un método de instancia. Y debido a que un método de instancia debería lanzarse si el objeto al que se está llamando es null
, también debería hacerlo el método de extensión.
* Como nota al margen, esta es exactamente la situación que enfrentaron los diseñadores de LINQ: cuando se lanzó C # 3.0, ya había millones de clientes que usaban System.Collections.IEnumerable
y System.Collections.Generic.IEnumerable<T>
, tanto en sus colecciones como en foreach
loops. Estas clases devolvieron IEnumerator
objetos que solo tenían los dos métodos Current
y MoveNext
, por lo que agregar cualquier método de instancia adicional requerido, como Count
, Any
, etc., estaría rompiendo estos millones de clientes. Entonces, para proporcionar esta funcionalidad (especialmente porque se puede implementar en términos de Current
y MoveNext
con relativa facilidad), lo lanzaron como métodos de extensión, que se pueden aplicar a cualquier instancia existente de IEnumerable
y También puede ser implementado por clases de manera más eficiente. Si los diseñadores de C # hubieran decidido lanzar LINQ el primer día, se les habría proporcionado como métodos de instancia de IEnumerable
, y probablemente habrían diseñado algún tipo de sistema para proporcionar implementaciones de interfaz predeterminada de esos métodos.