Cuándo usar clases estáticas en C# [duplicado]

Resuelto pbh101 asked hace 16 años • 11 respuestas

Esto es lo que MSDN tiene que decir en Cuándo utilizar clases estáticas :

static class CompanyInfo
{
    public static string GetCompanyName() { return "CompanyName"; }
    public static string GetCompanyAddress() { return "CompanyAddress"; }
    //...
}

Utilice una clase estática como 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 simple y rápida porque no es necesario crear un objeto para llamar a sus métodos. Es útil organizar los métodos dentro de la clase de manera significativa, como los métodos de la clase Math en el espacio de nombres del Sistema.

Para mí, ese ejemplo no parece cubrir muchos escenarios de uso posibles 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?

pbh101 avatar Oct 28 '08 03:10 pbh101
Aceptado

Escribí mis pensamientos sobre las clases estáticas en una respuesta anterior de Stack Overflow: 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 métodos auxiliares que de otro modo estarían por ahí causando redundancia y un infierno de mantenimiento. Son muy fáciles de usar, no se crean instancias ni se eliminan, simplemente dispara y olvida. Supongo que este fue mi primer intento involuntario de crear una arquitectura orientada a servicios: muchos servicios sin estado que simplemente hicieron su trabajo y nada más. Sin embargo, a medida que el sistema crece, aparecerán dragones.

Polimorfismo

Digamos que tenemos el método UtilityClass.SomeMethod que felizmente funciona. De repente necesitamos cambiar ligeramente la funcionalidad. La mayor parte de la funcionalidad es la misma, pero de todos modos tenemos que cambiar un par de piezas. Si no hubiera sido un método estático, podríamos crear una clase derivada y cambiar el contenido del método según fuera 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 ella, pero eso es simplemente asqueroso.

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 a través de su interfaz. Esto nos impide utilizar clases estáticas como parte de un patrón de estrategia. Podríamos solucionar algunos problemas pasando delegados en lugar de interfaces .

Pruebas

Básicamente, esto 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 código de prueba. Nuevamente, podemos resumirlos, pero requerirá que cambiemos grandes partes de nuestro código solo para poder aceptar envoltorios en lugar de los objetos reales.

Fomenta las manchas

Como los métodos estáticos generalmente se usan como métodos de utilidad y los métodos de utilidad generalmente tienen propósitos diferentes, rápidamente terminaremos con una clase grande llena de funcionalidades no coherentes; idealmente, cada clase debería tener un propósito único dentro del sistema. Preferiría tener cinco veces las clases siempre que sus propósitos estén bien definidos.

Deslizamiento de parámetros

Para empezar, ese pequeño y lindo método estático podría tomar un solo parámetro. A medida que crece la funcionalidad, se agregan un par de parámetros nuevos. Pronto se agregan más parámetros que son opcionales, por lo que creamos sobrecargas del método (o simplemente agregamos valores predeterminados, en idiomas que los admitan). En poco tiempo, tenemos un método que requiere 10 parámetros. Sólo los tres primeros son realmente necesarios; los parámetros 4 a 7 son opcionales. Pero si se especifica el parámetro 6, también es necesario 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 resolver esto tomando los parámetros requeridos en el constructor y permitir al usuario establecer 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 alcanzado esta complejidad, lo más probable es que de todos modos necesite estar en su propia clase.

Exigir a los consumidores que creen una instancia de clases sin ningún motivo

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, sin tener uso posterior para la instancia? Crear una instancia de una clase es una operación muy económica en la mayoría de los idiomas, por lo que la velocidad no es un problema. Agregar una línea adicional de código al consumidor es un bajo costo para sentar las bases de una solución mucho más mantenible en el futuro. Y finalmente, si desea evitar la creación de instancias, simplemente cree un contenedor singleton de su clase que permita una fácil reutilización, aunque esto exige que su clase no tenga estado. Si no es sin estado, aún puede crear métodos contenedores estáticos que manejen todo y al mismo tiempo le brinden todos los beneficios a largo plazo. Finalmente, también puedes crear una clase que oculte la creación de instancias como si fuera un singleton: MyWrapper.Instance es una propiedad que simplemente devuelvenew MyClass();

Sólo un Sith trata con absolutos

Por supuesto, hay excepciones a mi aversión por los métodos estáticos. Las verdaderas clases de utilidad que no presentan ningún riesgo de inflación son casos excelentes para métodos estáticos: System.Convert como ejemplo. Si su proyecto es único y no requiere mantenimiento futuro, la arquitectura general realmente no es muy importante (estática o no estática, realmente 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. Siempre que haya un razonamiento detrás de la diferenciación y esté estandarizada. No hay nada peor que observar una capa empresarial repleta de diferentes métodos de implementación.

Mark S. Rasmussen avatar Oct 27 '2008 21:10 Mark S. Rasmussen

Al decidir si hacer una clase estática o no estática, debe observar qué información está tratando de representar. Esto implica un estilo de programación más " ascendente " en el que se centra primero en los datos que se representan. ¿La clase en la que estás escribiendo es un objeto del mundo real como una piedra o una silla? Estas cosas son físicas y tienen atributos físicos como el color y el peso, lo que le indica que es posible que desee crear instancias de varios objetos con diferentes propiedades. Quizás quiera una silla negra Y una silla roja al mismo tiempo. Si alguna vez necesita dos configuraciones al mismo tiempo, sabrá instantáneamente que querrá crear una instancia como un objeto para que cada objeto pueda ser único y existir al mismo tiempo.

Por otro lado, las funciones estáticas tienden a prestarse más a acciones que no pertenecen a un objeto del mundo real o a un objeto que se pueda 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 se presta más a la programación " de arriba hacia abajo ". Se pueden utilizar métodos estáticos para estos casos en los que no tiene sentido que un 'objeto' realice la tarea. Al obligarlo a usar clases, esto simplemente hace que sea más fácil agrupar la funcionalidad relacionada, lo que le ayuda a crear código más fácil de mantener.

La mayoría de las clases pueden representarse de forma estática o no estática, pero cuando tengas dudas, simplemente regresa a tus raíces de programación orientada a objetos e intenta pensar en lo que estás representando. ¿Es este un objeto que realiza una acción (un automóvil que puede acelerar, desacelerar, girar) o algo más abstracto (como mostrar resultados)?

¡Ponte en contacto con tu programación orientada a objetos interior y nunca te equivocarás!

Despertar avatar Feb 01 '2012 02:02 Despertar