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


Esta pregunta ya tiene una respuesta aquí:

Esto es lo que MSDN tiene que decir debajo Cuándo usar clases estáticas:

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

Usa una clase estática como una unidad de   organización de métodos no   asociado con objetos particulares.   Además, una clase estática puede hacer que su   implementación más simple y más rápida   porque no tienes 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 suites sin estado de funciones relacionadas, pero eso es todo. Entonces, ¿bajo qué circunstancias debería (y no debería) declararse estática una clase?


534
2017-10-27 20:53


origen


Respuestas:


Escribí mis pensamientos sobre clases estáticas en una respuesta anterior de Stack Overflow: Clase con método único: ¿mejor enfoque?

Solía ​​amar las clases de utilidad llenas de métodos estáticos. Hicieron una gran consolidación de los métodos de ayuda que, de otro modo, estarían alrededor causando redundancia y mantenimiento. Son muy fáciles de usar, sin creación de instancias, sin eliminación, solo olvídate. Creo que este fue mi primer intento involuntario de crear una arquitectura orientada a servicios: muchos servicios apátridas que simplemente hicieron su trabajo y nada más. Sin embargo, a medida que el sistema crece, vienen los dragones.

Polimorfismo

Digamos que tenemos el método UtilityClass.SomeMethod que alegremente suena. De repente, necesitamos cambiar la funcionalidad un poco. La mayor parte de la funcionalidad es la misma, pero tenemos que cambiar un par de partes, no obstante. Si no hubiera sido un método estático, podríamos hacer 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, 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 dado que no podemos anular los métodos estáticos, las clases estáticas son inútiles cuando necesitamos pasarlas por su interfaz. Esto nos impide usar clases estáticas como parte de un patrón de estrategia. Podríamos corregir algunos problemas pasar delegados en lugar de interfaces.

Pruebas

Esto básicamente va de la mano con los problemas de interfaz mencionados anteriormente. Como nuestra capacidad de 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 partes grandes de nuestro código solo para poder aceptar envoltorios en lugar de los objetos reales.

Fosters blobs

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

Parámetro creep

Para empezar, ese pequeño y lindo 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 más 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 primeros tres son realmente necesarios, los parámetros 4-7 son opcionales. Pero si se especifica el parámetro 6, también se requieren rellenar 7-9 ... Si hubiéramos creado una clase con el único propósito de hacer lo que este método estático hicimos, podríamos resolver esto tomando en cuenta los parámetros requeridos en el constructor, y permite 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 crecido a esta cantidad de complejidad, lo más probable es que tenga que pertenecer a su propia clase.

Exige que los consumidores creen 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 único método, sin tener uso para la instancia posterior? Crear una instancia de una clase es una operación muy, muy barata en la mayoría de los lenguajes, por lo que la velocidad no es un problema. Agregar una línea adicional de código al consumidor es un costo bajo para sentar las bases de una solución mucho más fácil de mantener en el futuro. Y, por último, si desea evitar crear instancias, simplemente cree un contenedor único de su clase que permita una fácil reutilización, aunque esto exige que su clase sea apátrida. Si no es apátrida, puede crear métodos de envoltura estáticos que manejen todo, al tiempo que le brindan todos los beneficios a largo plazo. Finalmente, también puede crear una clase que oculte la creación de instancias como si fuera un singleton: MyWrapper.Instance es una propiedad que simplemente regresa new MyClass();

Solo un Sith trata en absolutos

Por supuesto, hay excepciones a mi disgusto por los métodos estáticos. Las verdaderas clases de utilidad que no presentan ningún riesgo para la hinchazón son casos excelentes para los métodos estáticos: System.Convert como ejemplo. Si su proyecto es único y no requiere mantenimiento futuro, la arquitectura general 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 usar también métodos estáticos, y viceversa. Mientras haya un razonamiento detrás de la diferenciación y esté estandarizado. No hay nada peor que mirar por encima de una capa de negocios con diferentes métodos de implementación.


647
2017-10-27 21:01



Al decidir si hacer que una clase sea estática o no estática, debe ver qué información está tratando de representar. Esto implica un más 'de abajo hacia arriba'estilo de programación donde te enfocas en los datos que estás representando primero. Es la clase en la que estás escribiendo 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 indica que es posible que desee crear instancias de objetos múltiples con diferentes propiedades. Es posible que desee una silla negra Y una silla roja al mismo tiempo. Si alguna vez necesita dos configuraciones al mismo tiempo, inmediatamente sabrá que desea crear una instancia como un objeto para que cada objeto pueda ser único y existir al mismo tiempo.

En el otro extremo, las funciones estáticas tienden a prestar más a las acciones que no pertenecen a un objeto del mundo real o un objeto que puede representar fácilmente. Recuerda que los predecesores de C # son C ++ y C, donde puedes definir funciones globales que no existen en una clase. Esto le da más a 'De arriba hacia abajo'programación. Los métodos estáticos se pueden usar 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, lo que te ayuda a crear un código más fácil de mantener.

La mayoría de las clases pueden representarse estáticas o no estáticas, pero cuando tenga dudas simplemente vuelva a las raíces de su OOP y trate de pensar sobre 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).

¡Ponte en contacto con tu OOP interno y nunca te equivocarás!


127
2018-02-01 02:50



Para C # 3.0, los métodos de extensión solo pueden existir en clases estáticas de nivel superior.


35
2017-10-27 20:57



Si usa herramientas de análisis de código (p. FxCop), te recomendará que marques un método static si ese método no accede a los datos de la instancia. La razón es que hay una ganancia de rendimiento. MSDN: CA1822 - Marca miembros como estáticos.

Es más una guía que una regla, realmente ...


21
2017-10-27 21:39



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);
   }
}

Es posible que incluso haya notado que se llama IoC con un acceso estático. Más del tiempo para mí, si puede llamar a métodos estáticos en una clase, eso es todo lo que puede hacer, así que marcó la clase como estática para mayor claridad.


12
2017-10-27 21:11



Empecé a usar clases estáticas cuando deseo usar funciones, en lugar de clases, como mi unidad de reutilización. Anteriormente, yo era todo sobre el mal de las clases estáticas. Sin embargo, aprendiendo F# me ha hecho verlos bajo una nueva luz.

¿Qué quiero decir con esto? Bueno, cuando trabajes en un super SECO código, termino con un montón de clases de método único. Puedo simplemente colocar estos métodos en una clase estática y luego insertarlos en dependencias usando un delegado. Esto también juega muy bien con mi inyección de dependencia (DI) contenedor de elección Autofac.

Por supuesto, tomar una dependencia directa de un método estático todavía generalmente malvado (hay algunos usos no malvados).


9
2017-07-01 09:34



Utilizo las clases estáticas como un medio para definir "funcionalidad adicional" que un objeto de un tipo dado podría usar bajo un contexto específico. Por lo general, resultan ser clases de utilidad.

Aparte de eso, creo que "Usar una clase estática como unidad de organización para métodos no asociados con objetos particulares". describir bastante bien su uso previsto.


8
2017-10-27 21:05