Хобрук: Ваш путь к мастерству в программировании

Почему реализация singleton в C # 6.0 не требует флага beforefieldinit?

Я пытаюсь понять, почему это правильная реализация паттерна Синглтон:

public sealed class Singleton : ISingleton
{
    public static Singleton Instance { get; } = new Singleton();

    private Singleton() { }

    // methods
}

А как насчет флага beforefieldinit? Согласно статье Джона Скита:

Ленивость инициализаторов типов гарантируется .NET только в том случае, если тип не помечен специальным флагом, называемым beforefieldinit. К сожалению, компилятор C # (по крайней мере, как это предусмотрено в среде выполнения .NET 1.1) помечает все типы, которые не имеют статического конструктора (т. Е. Блок, который выглядит как конструктор, но помечен как статический) как beforefieldinit.

Статический конструктор не нужен в новейшей версии C #?

Приведенный выше код является реализацией SystemClock в проекте NodaTime Джоном Скитом ».

ИЗМЕНИТЬ код Джона Скита для справки (почему я упоминаю этот флаг beforefieldinit):

public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();

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

    private Singleton()
    {
    }

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

  • А что насчет этого флага? Я не понимаю вопроса. 21.03.2016
  • @usr см. правку :) 21.03.2016
  • Существует нерешенная проблема дизайна языка C # для явного указания поведения beforefieldinit: github.com/dotnet/roslyn/ проблемы / 4448 (к сведению) 21.03.2016
  • Рослин онлайн говорит, что тип будет помечен как beforefieldinit: tryroslyn.azurewebsites.net/ #f: r / 21.03.2016
  • Проблема с beforefieldinit относится к лени создания экземпляра, а не к тому, является ли реализация правильным и безопасным синглтоном. В той же публикации Джона Скита, на которую вы ссылаетесь, есть раздел «Производительность против лени», в котором более подробно рассказывается, почему вам может быть небезразлична лень или нет. 21.03.2016

Ответы:


1

Оба являются правильными одноэлементными реализациями. Нужен ли вам статический конструктор просто, зависит от того, насколько вы заботитесь о полной лени. Если вы действительно не хотите, чтобы синглтон создавался до тех пор, пока он не будет использован вызывающей стороной, у вас должен быть статический конструктор или использовать Lazy<T>. Конечно, вы можете использовать статический конструктор в коде C # 6:

public sealed class Singleton : ISingleton
{
    public static Singleton Instance { get; } = new Singleton();

    static Singleton() { }
    private Singleton() { }

    // methods
}
21.03.2016
  • теперь компилятор не помечает по умолчанию статический конструктор перед fieldinit, верно? 21.03.2016
  • @ EʜsᴀɴSᴀᴊᴊᴀᴅ: Мне не известно о каких-либо изменениях по этому поводу, но я проверю. 21.03.2016
  • @ EʜsᴀɴSᴀᴊᴊᴀᴅ: Тогда я предлагаю вам задать новый, очень конкретный вопрос. Я только что подтвердил, что компилятор C # по-прежнему добавляет beforefieldinit, если нет статического конструктора. 21.03.2016
  • @ EʜsᴀɴSᴀᴊᴊᴀᴅ: Конечно, я не думаю, что когда-либо предполагал, что это будет null. Он просто влияет на время выполнения инициализатора типа. 21.03.2016
  • Я пробовал со статическим конструктором и без него, и это кажется противоположным тому, что вы пишете? без статического ctor при вызове статического метода он не будет инициализировать поля, со статическим ctor он всегда инициализирует их - я только что добавил статический метод Stub, который возвращает жестко закодированную строку - всякий раз, когда я добавляю статический ctor, он всегда печатает запись консоли, которую я добавил в частный ctor, даже если я просто вызываю Singleton.Stub (), если я прокомментирую статический ctor, он не инициализирует экземпляр и не вызывает частный ctor (проверено в режиме выпуска .NET 4) . 24.05.2016
  • @BornToCode: я предлагаю вам задать новый вопрос с реальным кодом, чтобы я мог объяснить поведение. Это частично зависит от того, что делает этот статический метод. 24.05.2016
  • @JonSkeet - Спасибо, я только что сделал. Это здесь. 24.05.2016
  • @JonSkeet public static Lazy<Singleton> Instance => new Lazy<Singleton>(() => new Singleton()); Итак, в C # 6 полной лени можно добиться вот так? 29.11.2017
  • @Givi: Нет, это даст вам новый синглтон каждый раз, когда вы будете использовать свойство. Но вы можете использовать public static Lazy<Singleton> Instance { get; } = new Lazy<Singleton>(() => new Singleton()); - вам все равно может понадобиться статический конструктор, и возврат Lazy<Singleton>, а не Singleton, вероятно, тоже не идеален. 29.11.2017
  • Новые материалы

    Решения DBA Metrix
    DBA Metrix Solutions предоставляет удаленного администратора базы данных (DBA), который несет ответственность за внедрение, обслуживание, настройку, восстановление базы данных, а также другие..

    Начало работы с Блум
    Обзор и Codelab для генерации текста с помощью Bloom Оглавление Что такое Блум? Некоторые предостережения Настройка среды Скачивание предварительно обученного токенизатора и модели..

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

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

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...