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();
}
}
Desejo implementar o padrão Singleton de Jon Skeet em meu aplicativo atual em C #.
Eu tenho duas duvidas no código
Como é possível acessar a classe externa dentro da classe aninhada? Quero dizer
internal static readonly Singleton instance = new Singleton();
É algo chamado fechamento?
Não consigo entender este comentário
// Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit
o que esse comentário nos sugere?
c#
.net
design-patterns
architecture
singleton
amutha
fonte
fonte
Respostas:
Não, isso não tem nada a ver com fechamentos. Uma classe aninhada tem acesso aos membros privados de sua classe externa, incluindo o construtor privado aqui.
Leia o meu artigo no beforefieldinit . Você pode ou não querer o construtor estático não operacional - isso depende da preguiça que você precisa. Você deve estar ciente de que o .NET 4 altera um pouco a semântica de inicialização de tipo real (ainda dentro da especificação, mas mais preguiçoso do que antes).
Você realmente precisa desse padrão? Tem certeza de que não pode se safar:
fonte
Lazy<T>
para que você não precise declarar um construtor estático para oBeforeFieldInit
efeito colateral mágico ?FieldBeforeInit
éMahaBharata
deMicrosoft
Em relação à pergunta (1): A resposta de Jon está correta, pois ele marca implicitamente a classe 'Nested' como privada, não a tornando pública ou interna :-). Você pode fazê-lo explicitamente adicionando 'private':
Em relação à pergunta (2): basicamente, o que a postagem sobre beforeinitfield e a inicialização de tipo dizem é que, se você não tiver um construtor estático, o tempo de execução poderá inicializá-lo a qualquer momento (mas antes de usá-lo). Se você tiver um construtor estático, seu código no construtor estático poderá inicializar os campos, o que significa que o tempo de execução só pode inicializar o campo quando você solicitar o tipo.
Portanto, se você não deseja que o tempo de execução inicialize os campos 'proativamente' antes de usá-los, adicione um construtor estático.
De qualquer maneira, se você estiver implementando singletons, deseja que ele seja inicializado o mais preguiçosamente possível e não quando o tempo de execução achar que deve inicializar sua variável - ou você provavelmente não se importa. Da sua pergunta, suponho que você os queira o mais tarde possível.
Isso leva ao post de Jon sobre o singleton , que é o tópico subjacente desta pergunta na IMO. Ah e as dúvidas :-)
Eu gostaria de salientar que o singleton # 3, que ele marcou como 'errado', está realmente correto (porque o lock's implica automaticamente uma barreira de memória na saída ). Também deve ser mais rápido que o singleton nº 2 quando você usa a instância mais de uma vez (que é mais ou menos o ponto de um singleton :-)). Portanto, se você realmente precisa de uma implementação preguiçosa de singleton, eu provavelmente optaria por essa - pelas simples razões de que (1) é muito claro para todos que lêem seu código o que está acontecendo e (2) você sabe o que acontecerá com exceções.
Caso você esteja se perguntando: eu nunca usaria o singleton nº 6 porque pode facilmente levar a conflitos e comportamento inesperado, com exceções. Para obter detalhes, consulte: modo de bloqueio do preguiçoso , especificamente ExecutionAndPublication.
fonte
Regarding question (1): The answer from Jon is correct ...
Jon Skeet está sempre correto ....