¿Por qué elegir una clase estática en lugar de una implementación singleton?

El estático vs. La pregunta de Singleton ha sido discutida muchas veces en SO.
Sin embargo, todas las respuestas señalaron las muchas ventajas de un singleton.
Mi pregunta es: ¿cuáles son las ventajas de una clase estática sobre un singleton? ¿Por qué no simplemente elegir un singleton cada vez?

La clase estática es una herramienta técnica en su caja, básicamente una función de idioma.

Singleton es un concepto arquitectónico.

Puede usar una clase estática como medio para implementar el concepto de singleton. O puede usar algún otro enfoque.

Con clases estáticas en C # existen dos peligros potenciales si no tienes cuidado.

  • Los recursos solicitados no se liberarán hasta el final de la vida útil de la aplicación
  • Los valores de las variables estáticas se comparten dentro de una aplicación. Especialmente malo para las aplicaciones ASP.NET, porque estos valores se compartirán entre todos los usuarios de un sitio que resida en un dominio de aplicación particular.

Desde MSDN

Las clases estáticas y los miembros de la clase se utilizan para crear datos y funciones a los que se puede acceder sin crear una instancia de la clase. Los miembros de clase estática se pueden utilizar para separar datos y comportamientos que son independientes de cualquier identidad de objeto: los datos y las funciones no cambian independientemente de lo que le ocurra al objeto. Las clases estáticas se pueden usar cuando no hay datos o comportamientos en la clase que dependen de la identidad del objeto.

Un punto clave es que las clases estáticas do not require an instance reference . También tenga en cuenta que las clases estáticas están habilitadas específicamente por el lenguaje y el comstackdor.

Las clases Singleton son solo clases codificadas por el usuario que implementan el patrón de diseño de Singleton . El objective de Singleton es restrict instantiation of an class to a single instance .

Si codificaras cada clase estática como singleton, tendrías que instanciar la clase cada vez que la usaras.

es decir

 Console.WriteLine('Hello World'); 

se convertiría

 Console c = Console.getInstance(); c.WriteLine('Hello World'); 

Yo diría que ambas son (generalmente) soluciones pobres. Hay algunos casos de uso para clases estáticas, principalmente simples de utilidad (me vienen a la mente los métodos de extensión en C # 3.0). Sin embargo, con cualquier grado de complejidad, los problemas de comprobación comienzan a aparecer.

Diga que la clase A depende de la clase estática B. Desea probar la clase A aisladamente. Eso es difícil.

Entonces vas con un Singleton. Usted tiene el mismo problema: la clase A depende del singleton B. No puede probar la clase A aisladamente.

Cuando la clase B tiene otras dependencias (como tocar una base de datos) o es mutable (otras clases pueden cambiar su estado global), el problema se agrava.

Las bibliotecas de contenedores de IoC ( Inversión de control ) son una solución a este problema; te permiten definir las Viejas clases simples como una larga vida útil. Cuando se combina con una biblioteca burlona, ​​pueden hacer que tu código sea muy comprobable.

Las clases estáticas son mucho más fáciles de implementar: he visto muchos bashs de singleton seguros para subprocesos en C # que emplean esquemas de locking ingenuos en lugar de depender de la inicialización de campos estáticos garantizados por tiempo de ejecución en tiempo de ejecución (opcionalmente dentro de una clase anidada para retrasar la creación de instancias )

Aparte de eso, creo que los singleton son geniales si necesitas pasar una referencia a un objeto que implementa una interfaz específica, cuando esa ‘implementación’ debe ser singleton, algo que no puedes hacer con clases estáticas.

Una consideración que no veo mencionada es que preferir una solución usando una instancia de una clase (singletons, o su equivalente DI) le permite proporcionar una clase en la que otros usuarios de su código pueden definir métodos de extensión, ya que solo los métodos de extensión trabajar con clases no estáticas como this parámetro. En otras palabras, si tiene una línea como:

 GlobalSettings.SomeMethod(); 

Luego, sintácticamente, lo único que se puede acceder a través de GlobalSettings son los miembros que usted proporciona. Por el contrario, si GlobalSettings es una instancia (única o no), los consumidores pueden agregar sus propias extensiones a GlobalSettings que de otro modo no podrían hacer:

 application.GlobalSettings.CustomSomethingOrOther(); 

o

 GlobalSettings.Instance.CustomSomethingOrOther();