Одиночка (Singleton, Синглтон) - порождающий паттерн, который гарантирует, что для определенного класса будет создан только один экземпляр, а также предоставит к этому экземпляру точку доступа.
Все реализации одиночки сводятся к тому, чтобы скрыть конструктор по умолчанию и создать публичный статический метод, который и будет контролировать жизненный цикл экземпляра-одиночки.
Если у вас есть доступ к классу одиночки, значит, будет доступ и к этому статическому методу. Из какой точки кода вы бы его ни вызвали, он всегда будет отдавать один и тот же объект.
### Singleton без lazy-реализации
Обычно, когда реализуется паттерн Singleton, то применяется Lazy-реализация, то есть экземпляр создается только когда произойдет первый вызов класса.
Можно упростить реализацию singleton и сделать так, чтобы при запуске игры, экземпляр класса сразу инициализировался.
Я столкнулся с проблемой, что некоторые поля (например `_methodsDictionary`) в классе были null, когда код в конструкторе обращался к ним.
Так происходит из-за того, что в C# порядок инициализации полей определяется порядком их объявления в коде.
Поле `I` было объявлено раньше, чем `_methodsDictionary`, поэтому его инициализация (и соответствующий вызов конструктора класса) произошла раньше, чем инициализация `_methodsDictionary`.
Конструктор пытался работать с полем `_methodsDictionary`, которое ещё не было инициализировано.
Решение проблемы заключается в изменении порядка объявления полей таким образом, все поля былы объявлены и инициализированы до (перед) `I`. Это обеспечивает корректную инициализацию всех полей
Итак, важный урок, который можно извлечь из этого опыта: в C#, порядок инициализации полей определяется порядком их объявления в коде, и это может иметь существенное значение, когда инициализация одного поля зависит от другого.