unity template make lazy explained example ejemplo code c# .net singleton

c# - template - ¿Una implementación obvia de singleton para.NET?



singleton service c# (7)

Todo el asunto de la ineficiencia de: ...

¿Qué ineficiencia?

Esas instrucciones darán como resultado fragmentos de código de ensamblaje extremadamente rápidos. Estoy completamente seguro de que no hay nada que ganar al tratar de "optimizar" esto. Incluso si se te ocurre algo más rápido, tendrá un costo de complejidad significativo.

A menos que tenga evidencia positiva de que este código está afectando su rendimiento, debe usar el enfoque más simple que resuelva su problema.

Estaba pensando en el clásico problema de la inicialización perezosa de singleton, todo el asunto de la ineficiencia de:

if (instance == null) { instance = new Foo(); } return instance;

Cualquiera que sepa lo que es un Singleton está familiarizado con el problema (solo lo necesita una vez). Es trivial pero irritante.

Entonces, pensé en una solución alternativa, al menos para .NET (aunque debería funcionar en cualquier lugar que tenga algún equivalente a los punteros de función)

public class Foo { private delegate Foo FooReturner(); private static Foo innerFoo; private static FooReturner fooReturnHandler = new FooReturner(InitialFooReturner); public static Foo Instance { get { return fooReturnHandler(); } } private static Foo InitialFooReturner() { innerFoo = new Foo(); fooReturnHandler = new FooReturner(NewFooReturner); return innerFoo; } private static Foo NewFooReturner() { return innerFoo; } }

En resumen, la instancia devuelve un método delegado. El delegado se establece inicialmente en un método que inicializa su instancia, luego cambia el delegado para que apunte a un método de retorno simple.

Ahora, me gusta pensar que no soy terrible en mi trabajo, pero no tengo pretensiones de ser asombroso. No he visto un ejemplo de este código en ninguna parte.

Ergo, llego a la conclusión de que me estoy perdiendo algo. Algo mayor. O bien que todo el problema es demasiado trivial como para molestarse en pensar mucho o esto hace algo horrible que destruirá el universo. O fallo en la búsqueda y, por lo tanto, no he visto a los cientos de desarrolladores que utilizan este método. Algo, de todos modos.

Esperaba que la buena gente aquí en Stack Overflow pudiera darme una idea de qué (dejando de lado la controversia sobre si uno debería usar un Singleton o no).

EDITAR para la aclaración:

Este no es un código de rendimiento (aunque sería interesante saber si el diseño degrada activamente el rendimiento más allá del modelo tradicional).

Fue escrito puramente como prueba de concepto, y soy más consciente de que no es seguro para subprocesos como debería serlo. ¿Hay alguna razón por la que NO se pueda hacer seguro para subprocesos por su propia naturaleza?


¿Has medido el rendimiento?

¿Crees que una llamada de función adicional es más barata que un if?

Estoy de acuerdo con los demás en que el uso del ctor estático funciona bien para esta inicialización. Esto también eliminará la condición de carrera inherente que tienes desde .net garantiza que los constructores estáticos solo serán llamados una vez.


Acabo de comenzar a programar en c # (proveniente de C ++, es un soplo de aire fresco) y esto es lo que uso para implementar patrones singleton.

public sealed class MyClass { #region make singleton static readonly Lazy<MyClass> _singleton = new Lazy<MyClass>(() => new MyClass()); public static MyClass Singleton { get { return _singleton.Value; } } private MyClass() { Initialize() }; #endregion Initialize() { /*TODO*/ }; }


El mejor método que he encontrado para crear un singleton es este:

public class Singleton { static public Singleton Instance { get; } = new Singleton(); private Singleton() { ... } }

Es muy conciso y, lo que es más importante, también es seguro para subprocesos , lo que puede ser muy molesto de detectar y corregir a medida que la aplicación madura.

Actualización: Mostrar que es perezoso ...

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SingletonTest { class MySingleton { static public MySingleton Instance { get; } = new MySingleton(); private MySingleton() { Console.WriteLine("Created MySingleton"); } public void DoSomething() { Console.WriteLine("DoSomething"); } } class Program { static void Main(string[] args) { Console.WriteLine("Starting Main"); MySingleton.Instance.DoSomething(); } } }

Salida:

Starting Main Created MySingleton DoSomething


Para evitar tener que copiar el código singleton, podría hacer que el tipo sea genérico, como tal:

public abstract class Singleton<T> where T: class, new() { public static T Instance { get { return Nested.instance; } } private class Nested { // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Nested() { } internal static readonly T instance = new T(); } } public sealed class MyType : Singleton<MyType> { } class Program { static void Main() { // two usage pattterns are possible: Console.WriteLine( ReferenceEquals( Singleton<MyType>.Instance, MyType.Instance ) ); Console.ReadLine(); } }


Siempre uso este uno regular (no perezoso) (puede anidarlo como en los otros ejemplos): (requiere el using System.Reflection; )

public class SingletonBase<T> where T : class { static SingletonBase() { } public static readonly T Instance = typeof(T).InvokeMember(typeof(T).Name, BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, null, null) as T; }


Este es el patrón canónico, seguro de hilo, perezoso de Singleton en C # :

public sealed class Singleton { Singleton(){} public static Singleton Instance { get { return Nested.instance; } } class Nested { // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Nested() {} internal static readonly Singleton instance = new Singleton(); } }