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();
}
}
Deseo implementar el patrón Singleton de Jon Skeet en mi aplicación actual en C #.
Tengo dos dudas sobre el código
¿Cómo es posible acceder a la clase externa dentro de la clase anidada? quiero decir
internal static readonly Singleton instance = new Singleton();
¿Se llama algo cierre?
No puedo entender este comentario.
// Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit
¿Qué nos sugiere este comentario?
c#
.net
design-patterns
architecture
singleton
amutha
fuente
fuente
Respuestas:
No, esto no tiene nada que ver con los cierres. Una clase anidada tiene acceso a los miembros privados de su clase externa, incluido el constructor privado aquí.
Lea mi artículo sobre beforefieldinit . Es posible que desee o no el constructor estático no operativo: depende de las garantías de pereza que necesite. Debe tener en cuenta que .NET 4 cambia un poco la semántica de inicialización de tipo real (aún dentro de las especificaciones, pero más vago que antes).
¿ Realmente necesitas este patrón? ¿Estás seguro de que no puedes salirte con la tuya?
fuente
Lazy<T>
para no tener que declarar un constructor estático para elBeforeFieldInit
efecto secundario mágico ?FieldBeforeInit
esMahaBharata
deMicrosoft
Con respecto a la pregunta (1): La respuesta de Jon es correcta, ya que él marca implícitamente la clase como 'Anidada' privada al no hacerla pública o interna :-). También podría hacerlo explícitamente agregando 'privado':
Con respecto a la pregunta (2): básicamente, lo que la publicación sobre beforeinitfield y type initialization le dice es que si no tiene un constructor estático, el tiempo de ejecución puede inicializarlo en cualquier momento (pero antes de usarlo). Si tiene un constructor estático, su código en el constructor estático puede inicializar los campos, lo que significa que el tiempo de ejecución solo puede inicializar el campo cuando solicita el tipo.
Entonces, si no desea que el tiempo de ejecución inicialice los campos 'proactivamente' antes de usarlos, agregue un constructor estático.
De cualquier manera, si está implementando singletons, desea que se inicialice lo más vago posible y no cuando el tiempo de ejecución cree que debería inicializar su variable, o probablemente simplemente no le importe. Por su pregunta, supongo que los quiere lo más tarde posible.
Eso lleva a la publicación de Jon sobre singleton 's, que es IMO el tema subyacente de esta pregunta. Ah y las dudas :-)
Me gustaría señalar que su singleton # 3, que marcó 'incorrecto', es realmente correcto (porque el bloqueo implica automáticamente una barrera de memoria al salir ). También debería ser más rápido que el singleton # 2 cuando usa la instancia más de una vez (que es más o menos el punto de un singleton :-)). Entonces, si realmente necesita una implementación de singleton perezosa, probablemente iría por esa, por las simples razones de que (1) es muy claro para todos los que leen su código lo que está sucediendo y (2) saben lo que sucederá con excepciones
En caso de que se pregunte: nunca usaría singleton # 6 porque puede conducir fácilmente a puntos muertos y comportamientos inesperados con excepciones. Para obtener detalles, consulte: modo de bloqueo de lazy , específicamente ExecutionAndPublication.
fuente
Regarding question (1): The answer from Jon is correct ...
Jon Skeet siempre tiene razón ...