Qual é a diferença entre esses modos de criar a instância estática para um singleton?
Pergunta
Eu tive um bug recentemente que só se manifesta quando a biblioteca foi construída como uma compilação de lançamento, em vez de uma compilação de depuração. A biblioteca é um .NET dll com uma COM invólucro e estou usando CoCreateInstance para criar uma classe da DLL em um aplicativo não gerenciado c ++. Quando eu finalmente rastreou o bug para baixo ele foi causado por acessar um objeto singleton. Eu tinha a instância singleton declarada assim:
private static readonly MyObjectType s_instance = new MyObjectType;
e, em seguida, acessada com:
public static MyObjectType Instance
{
get
{
return s_instance;
}
}
este estava falhando. Mudá-lo para:
private static MyObjectType s_instance;
public static MyObjectType Instance
{
get
{
if (s_instance==null)
{
s_instance = new MyObjectType();
}
return s_instance;
}
}
corrigiu o problema. Alguma idéia por que o uso inicial não funcionou e se existem quaisquer desvantagens para fazê-lo de qualquer forma?
A dll liberação parecia ser perfeitamente utilizável a partir de outro aplicativo gerenciado.
Solução
Tente adicionar um construtor estático (vazio), ou inicializar a Singleton em um construtor estático.
Jon Skeet tem uma discussão completa de padrões únicos aqui . Eu não sei por que ele falhou, mas a um palpite poderia relacionar com a bandeira "beforefieldinit". Veja seu quarto exemplo, onde ele adiciona um construtor estático para ajustar esta bandeira. Não tenho a pretensão de ser um especialista em beforefieldinit, mas este sintoma parece se encaixar alguns dos sintomas discutidos aqui .
Outras dicas
Apenas reiterando o que Marc Gravell disse, mas soa muito como um problema beforefieldinit, o que significa que o construtor estático vazio é a sua solução. Você precisaria para postar qualquer e todos os construtores na classe para obter uma resposta definitiva.
O segundo método tem a vantagem do carregamento lento (onde que é uma vantagem).