method - Cuándo usar clases estáticas en C#
use static class in c# (11)
Al decidir si hacer una clase estática o no estática, debe ver qué información está tratando de representar. Esto conlleva un estilo de programación más ''de abajo hacia arriba '' en el que se enfoca en los datos que está representando primero. ¿Es la clase en la que estás escribiendo un objeto del mundo real como una roca o una silla? Estas cosas son físicas y tienen atributos físicos como el color y el peso que le indican que es posible que desee crear una instancia de múltiples objetos con diferentes propiedades. Puede que quiera una silla negra Y una silla roja al mismo tiempo. Si alguna vez necesita dos configuraciones al mismo tiempo, entonces instantáneamente sabrá que querrá crear una instancia como un objeto para que cada objeto pueda ser único y exista al mismo tiempo.
En el otro extremo, las funciones estáticas tienden a prestar más a acciones que no pertenecen a un objeto del mundo real o un objeto que puede representar fácilmente. Recuerde que los predecesores de C # son C ++ y C, donde puede definir funciones globales que no existen en una clase. Esto presta más a la programación "de arriba a abajo ". Se pueden usar métodos estáticos para estos casos en los que no tiene sentido que un ''objeto'' realice la tarea. Al forzarte a usar clases, esto hace que sea más fácil agrupar la funcionalidad relacionada que te ayuda a crear un código más mantenible.
La mayoría de las clases se pueden representar ya sea estáticas o no estáticas, pero cuando tenga dudas, simplemente vuelva a sus raíces OOP e intente pensar en lo que está representando. Es este un objeto que está realizando una acción (un automóvil que puede acelerar, ralentizar, girar) o algo más abstracto (como mostrar la salida).
Póngase en contacto con su OOP interno y nunca podrá salir mal.
Esta pregunta ya tiene una respuesta aquí:
- Clase con método único - ¿el mejor enfoque? 14 respuestas
Esto es lo que MSDN tiene que decir bajo Cuándo usar clases estáticas :
static class CompanyInfo { public static string GetCompanyName() { return "CompanyName"; } public static string GetCompanyAddress() { return "CompanyAddress"; } //... }
Use una clase estática como una unidad de organización para métodos no asociados con objetos particulares. Además, una clase estática puede hacer que su implementación sea más sencilla y rápida porque no tiene que crear un objeto para llamar a sus métodos. Es útil organizar los métodos dentro de la clase de una manera significativa, como los métodos de la clase de Matemáticas en el espacio de nombres del Sistema.
Para mí, ese ejemplo no parece abarcar muchos posibles escenarios de uso para clases estáticas. En el pasado, he usado clases estáticas para conjuntos sin estado de funciones relacionadas, pero eso es todo. Entonces, ¿bajo qué circunstancias debería (y no debería) declararse estática una clase?
Basado en MSDN :
- No se puede crear la instancia para clases estáticas.
- Si la clase se declara como estática, la variable miembro debe ser estática para esa clase
- Sellado [No se puede heredar]
- No se puede contener el constructor de instancias.
- Gestión de la memoria
Ejemplo: los cálculos matemáticos (valores matemáticos) no cambian [CÁLCULO ESTÁNDAR PARA VALORES DEFINIDOS]
Comencé a usar clases estáticas cuando deseo usar funciones, en lugar de clases, como mi unidad de reutilización. Anteriormente, estaba todo sobre el mal de las clases estáticas. Sin embargo, aprender F# me ha hecho verlos desde una nueva perspectiva.
¿Qué quiero decir con esto? Bueno, digamos que al elaborar un código súper DRY , acabo con un montón de clases de un método. Puedo simplemente jalar estos métodos a una clase estática y luego inyectarlos en dependencias usando un delegado. Esto también funciona bien con mi contenedor de inyección de dependencias (DI) de elección Autofac.
Por supuesto, tomar una dependencia directa de un método estático todavía suele ser malo (hay algunos usos no malignos).
Escribí mis pensamientos sobre clases estáticas en una respuesta anterior de Desbordamiento de pila: Clase con método único: ¿el mejor enfoque?
Me encantaban las clases de utilidad llenas de métodos estáticos. Hicieron una gran consolidación de los métodos de ayuda que de otra manera estarían causando redundancia y un infierno de mantenimiento. Son muy fáciles de usar, no tienen instancias, no se eliminan, solo hay que disparar y olvidar. Supongo que este fue mi primer intento involuntario de crear una arquitectura orientada a servicios: muchos servicios sin estado que hicieron su trabajo y nada más. Sin embargo, a medida que un sistema crece, los dragones están llegando.
Polimorfismo
Digamos que tenemos el método UtilityClass.SomeMethod que felizmente zumba. De repente necesitamos cambiar la funcionalidad ligeramente. La mayor parte de la funcionalidad es la misma, pero todavía tenemos que cambiar un par de partes. Si no hubiera sido un método estático, podríamos crear una clase derivada y cambiar el contenido del método según sea necesario. Como es un método estático, no podemos. Claro, si solo necesitamos agregar funcionalidad antes o después del método anterior, podemos crear una nueva clase y llamar a la anterior dentro de él, pero eso es simplemente un asco.
Problemas de interfaz
Los métodos estáticos no se pueden definir a través de interfaces por razones lógicas. Y como no podemos anular los métodos estáticos, las clases estáticas son inútiles cuando necesitamos pasarlas por su interfaz. Esto nos hace incapaces de usar clases estáticas como parte de un patrón de estrategia. Podríamos solucionar algunos problemas pasando delegados en lugar de interfaces .
Pruebas
Esto básicamente va de la mano con los problemas de interfaz mencionados anteriormente. Como nuestra capacidad para intercambiar implementaciones es muy limitada, también tendremos problemas para reemplazar el código de producción con el código de prueba. Nuevamente, podemos envolverlos, pero requerirá que cambiemos grandes partes de nuestro código para poder aceptar envoltorios en lugar de los objetos reales.
Fomenta las manchas
Como los métodos estáticos se usan generalmente como métodos de utilidad y los métodos de utilidad generalmente tienen propósitos diferentes, terminaremos rápidamente con una clase grande llena de funcionalidad no coherente; idealmente, cada clase debe tener un solo propósito dentro del sistema. Preferiría tener cinco veces más clases, siempre que sus propósitos estén bien definidos.
Arrastramiento de parámetros
Para empezar, ese pequeño método estático e inocente podría tomar un solo parámetro. A medida que crece la funcionalidad, se agregan un par de nuevos parámetros. Pronto se agregan otros parámetros que son opcionales, por lo que creamos sobrecargas del método (o simplemente agregamos valores predeterminados, en los idiomas que los admiten). En poco tiempo, tenemos un método que toma 10 parámetros. Solo los tres primeros son realmente necesarios, los parámetros 4-7 son opcionales. Pero si se especifica el parámetro 6, también se debe completar 7-9 ... Si hubiéramos creado una clase con el único propósito de hacer lo que hizo este método estático, podríamos resolverlo tomando los parámetros requeridos en el constructor, y permitir que el usuario establezca valores opcionales a través de propiedades o métodos para establecer múltiples valores interdependientes al mismo tiempo. Además, si un método ha crecido a esta cantidad de complejidad, lo más probable es que tenga que estar en su propia clase de todos modos.
Exigir a los consumidores crear una instancia de clases sin ninguna razón.
Uno de los argumentos más comunes es: ¿por qué exigir que los consumidores de nuestra clase creen una instancia para invocar este método único, mientras que después no tienen ningún uso para la instancia? Crear una instancia de una clase es una operación muy barata en la mayoría de los idiomas, por lo que la velocidad no es un problema. Agregar una línea de código adicional al consumidor es un bajo costo para sentar las bases de una solución mucho más fácil de mantener en el futuro. Y, por último, si desea evitar la creación de instancias, simplemente cree un envoltorio singleton de su clase que permita una reutilización fácil, aunque esto hace que el requisito de que su clase sea sin estado. Si no es sin estado, aún puede crear métodos de envoltura estática que manejen todo, mientras que a la vez le ofrece todos los beneficios. Finalmente, también podría crear una clase que oculte la creación de instancias como si fuera un singleton: MyWrapper.Instance es una propiedad que simplemente devuelve new MyClass();
Sólo un Sith trata de absolutos.
Por supuesto, hay excepciones a mi aversión a los métodos estáticos. Las verdaderas clases de utilidad que no suponen ningún riesgo de hincharse son casos excelentes para métodos estáticos: System.Convert como ejemplo. Si su proyecto es único y no requiere ningún mantenimiento futuro, la arquitectura general realmente no es muy importante (estática o no estática, no importa), sin embargo, la velocidad de desarrollo sí lo es.
Estándares, estándares, estándares!
El uso de métodos de instancia no le impide utilizar también métodos estáticos, y viceversa. Mientras exista un razonamiento detrás de la diferenciación y se estandarice. No hay nada peor que mirar una capa de negocios en expansión con diferentes métodos de implementación.
Esta es otra pregunta antigua pero muy candente desde que comenzó la OOP. Hay muchas razones para usar (o no) una clase estática, por supuesto, y la mayoría de ellas se han cubierto en la multitud de respuestas.
Solo agregaré mis 2 centavos a esto, diciendo que, hago una clase estática, cuando esta clase es algo que sería único en el sistema y que realmente no tendría sentido tener ninguna instancia en el programa. Sin embargo, reservo este uso para grandes clases. Nunca declaro clases tan pequeñas como en el ejemplo de MSDN como "estáticas" y, ciertamente, no como clases que van a ser miembros de otras clases.
También me gusta señalar que los métodos estáticos y las clases estáticas son dos cosas diferentes a considerar. Las principales desventajas mencionadas en la respuesta aceptada son los métodos estáticos. Las clases estáticas ofrecen la misma flexibilidad que las clases normales (en lo que concierne a las propiedades y los parámetros), y todos los métodos utilizados en ellas deben ser relevantes para el propósito de la existencia de la clase.
Un buen ejemplo, en mi opinión, de un candidato para una clase estática es una clase de "procesamiento de archivos", que contendría todos los métodos y propiedades relevantes para los diversos objetos del programa para realizar operaciones complejas de procesamiento de archivos. Difícilmente tiene algún significado tener más de una instancia de esta clase y ser estático hará que esté disponible para todo en su programa.
Las clases estáticas son muy útiles y tienen un lugar, por ejemplo bibliotecas.
El mejor ejemplo que puedo proporcionar es la clase matemática .Net, una clase estática de espacio de nombres del sistema que contiene una biblioteca de funciones matemáticas.
Es como cualquier otra cosa, use la herramienta adecuada para el trabajo y, si no, se puede abusar de algo.
Dejar de lado las clases estáticas como incorrectas, no usarlas, o decir "solo puede haber una" o ninguna, es tan incorrecto como usarlas.
C # .Net contiene una serie de clases estáticas que se usan como la clase matemática.
Así que dada la correcta implementación son tremendamente útiles.
Tenemos una clase de Zona horaria estática que contiene una serie de funciones de zona horaria relacionadas con el negocio, no hay necesidad de crear múltiples instancias de la clase tanto como la clase Matemática que contiene un conjunto de funciones (métodos) relacionadas de Zona horaria globalmente accesibles en una clase estática .
Para C # 3.0, los métodos de extensión solo pueden existir en clases estáticas de nivel superior.
Si usa herramientas de análisis de código (por ejemplo, FxCop ), le recomendará que marque un método static
si ese método no accede a los datos de instancia. La razón es que hay una ganancia de rendimiento. MSDN: CA1822 - Marcar miembros como estáticos .
Es más una pauta que una regla, realmente ...
Solo uso clases estáticas para métodos de ayuda, pero con el advenimiento de C # 3.0, prefiero usar métodos de extensión para esos.
Rara vez utilizo métodos de clases estáticas por las mismas razones por las que rara vez uso el "patrón de diseño" singleton.
Tiendo a usar clases estáticas para fábricas. Por ejemplo, esta es la clase de registro en uno de mis proyectos:
public static class Log
{
private static readonly ILoggerFactory _loggerFactory =
IoC.Resolve<ILoggerFactory>();
public static ILogger For<T>(T instance)
{
return For(typeof(T));
}
public static ILogger For(Type type)
{
return _loggerFactory.GetLoggerFor(type);
}
}
Puede que incluso hayas notado que IoC se llama con un acceso estático. La mayoría de las veces, para mí, si puede llamar a métodos estáticos en una clase, eso es todo lo que puede hacer, así que marque la clase como estática para mayor claridad.
Utilizo clases estáticas como un medio para definir la "funcionalidad adicional" que un objeto de un tipo determinado podría usar en un contexto específico. Por lo general resultan ser clases de utilidad.
Aparte de eso, creo que "Use una clase estática como una unidad de organización para métodos no asociados con objetos particulares". Describe bastante bien su uso previsto.