В чем разница между этими способами создания статического экземпляра для синглтона?
Вопрос
Недавно у меня была ошибка, которая проявлялась только тогда, когда библиотека была построена как сборка релиза, а не как отладочная сборка. Библиотека представляет собой .NET dll с оболочкой COM, и я использую CoCreateInstance для создания класса из dll в неуправляемом приложении c ++. Когда я наконец обнаружил ошибку, она была вызвана доступом к одноэлементному объекту. У меня был экземпляр Singleton объявлен так:
private static readonly MyObjectType s_instance = new MyObjectType;
, а затем получил к нему доступ:
public static MyObjectType Instance
{
get
{
return s_instance;
}
}
это не удалось. Меняем его на:
private static MyObjectType s_instance;
public static MyObjectType Instance
{
get
{
if (s_instance==null)
{
s_instance = new MyObjectType();
}
return s_instance;
}
}
исправил проблему. Есть идеи, почему первоначальное использование не сработало и есть ли недостатки в том или ином случае?
Похоже, что dll-релиз идеально подходит для другого управляемого приложения.
Решение
Попробуйте добавить (пустой) статический конструктор или инициализируйте одиночный в статический конструктор.
Джон Скит подробно рассказывает о шаблонах синглтона здесь . Я не уверен, почему это не удалось, но, по-моему, это может относиться к "beforefieldinit" флаг. Посмотрите его 4-й пример, где он добавляет статический конструктор для настройки этого флага. Я не утверждаю, что являюсь экспертом в области beforefieldinit, но этот симптом, по-видимому, подходит к некоторым из обсуждаемых симптомов «> .
Другие советы
Просто повторяю то, что сказал Марк Гравелл, но это очень похоже на проблему beforefieldinit, что означает, что пустой статический конструктор - это ваше решение. Чтобы получить окончательный ответ, вам нужно опубликовать все конструкторы в классе.
Второй метод имеет преимущество ленивой загрузки (где это является преимуществом).