Почему «только для чтения» необходимо в следующей реализации Singleton? - PullRequest
5 голосов
/ 28 января 2011
public sealed class Singleton
{
    static readonly Singleton instance=new Singleton();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }

    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}

Я думаю, что даже при удалении ключевого слова readonly из экземпляра instance, синглтон все равно будет работать одинаково хорошо.

  • Его статический, может существовать только один экземпляр.
  • Значение не может быть изменено, так как оно не имеет установщика.
  • Это закрытый класс, не может быть подклассами.

Пожалуйста, помогите мне исправить мое понимание понятий здесь.

Ответы [ 4 ]

11 голосов
/ 28 января 2011

Потому что, если поле не было помечено только для чтения, оно может быть изменено в классе Singleton.Конечно, он по-прежнему не может быть изменен внешним миром, но синглтон действительно не является синглтоном, если существует более одного его экземпляра за время жизни вашей программы, а спецификатор readonly обеспечивает семантику, которую вы хотите использовать вкласс синглтона.

РЕДАКТИРОВАТЬ в ответ на:

  1. Его статический, существует только один экземпляр.
  2. Значение не может измениться, так как оно имеетнет установщика.

Статические переменные, безусловно, могут быть установлены для ссылки на разные объекты во время выполнения.Значение может измениться, если только внутри класса, потому что оно является частным.Если бы класс был реализован так, чтобы поле было назначено только один раз, на практике это не было бы проблемой.Однако, поскольку предполагается, что экземпляр синглтона никогда не изменится, модификатор readonly гарантирует эту семантику за пределами конструктора.Это не существенно , потому что клиенты класса не могут изменить ссылку, но это предпочтительнее, потому что это а) проясняет смысл кода и б) предотвращает изменение ссылки даже внутри класса.

7 голосов
/ 28 января 2011

Использование readonly не является обязательным в этом случае, но это то, что усиливает семантику кода, указывая природу поля.Лично я всегда использую ключевое слово readonly для всех объявлений полей, значение которых будет инициализировано только один раз.Это также может помочь компилятору выполнить некоторые оптимизации при определенных обстоятельствах.

0 голосов
/ 28 февраля 2013

Я удалил чтение только в классе, потому что хотел создать OneAtaTimeleton (вместо Singleton).

Почему? Ну, класс содержал некоторую конфигурацию, которую я хотел, чтобы пользователь (администратор) мог изменять во время работы приложения. Итак, я добавил статический метод Reload () в класс, который имеет:

instance = new Configuration();

отсюда и необходимость удалять readonly.

Частная версия конструктора загружает конфигурацию (нестатическим методом).

0 голосов
/ 28 января 2011

Я не думаю, что readonly должен присутствовать здесь - это имеет смысл только для ленивой инициализации.Если ваше статическое поле помечено как доступное только для чтения - оно может быть инициализировано только во время объявления или в статическом конструкторе.Если экземпляр не помечен как только для чтения - вы можете инициализировать его во время первого вызова свойства Instance.

Кстати, я думаю, что лучше использовать синглтон с двойной проверкой блокировки:

public sealed class Singleton
{
    private Singleton()
    {
       // Initialize here
    }

    private static volatile Singleton _singletonInstance;

    private static readonly Object syncRoot = new Object();

    public static Singleton Instance
    {
       get
       {
          if(_singletonInstance == null)
          {
             lock(syncRoot))
             {
                if(_singletonInstance == null)
                {   
                   _singletonInstance = new Singleton();
                }
             }
          }

          return _singletonInstance;
       }           
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...