Ваш код содержит частный статический инициализированный экземпляр:
private static Foo instance = new Foo();
Предполагаете ли вы, что это означает, что конструктор instance всегда будет запускаться до доступа к любому статическому методу, поэтому обеспечение инициализации bar
будет *
В однопоточном корпусе, я думаю, вы правы.
Последовательность событий будет:
- Позвоните на
Foo.BarLength()
- Статическая инициализация класса
Foo
(если еще не завершена)
- Статическая инициализация частного статического члена
instance
с экземпляром Foo
- Вход в
Foo.BarLength()
Однако статическая инициализация класса запускается только один раз для каждого домена приложения - и в IIRC нет блокировки, чтобы гарантировать, что он завершен до вызова любых других статических методов.
Итак, у вас может быть такой сценарий:
- Тема Альфа: Звоните на
Foo.BarLength()
- Thread Alpha: Статическая инициализация класса
Foo
(если еще не завершена) начинается
- Переключение контекста
- Тема бета: Звоните на
Foo.BarLength()
- Thread Beta: Нет вызова для статической инициализации класса
Foo
, поскольку это уже выполняется
- Тема бета: вход в
Foo.BarLength()
- Тема бета: доступ к
null
статическому члену instance
Анализатор Contracts не может знать, что вы никогда не будете выполнять код в многопоточном режиме, поэтому он должен ошибиться из-за осторожности.