Статическое чтение только против const

Я прочитал около const и static readonly полей. У нас есть несколько классов, которые содержат только постоянные значения. Используется для различных вещей в нашей системе. Поэтому мне интересно, если мои наблюдения верны:

Должны ли эти виды постоянных значений всегда быть static readonly для всего, что является публичным? И использовать только const для внутренних / защищенных / частных значений?

Что вы рекомендуете? Должен ли я даже не использовать поля static readonly, а использовать свойства, может быть?

вопрос задан 16.04.2009
Svish
61834 репутация

15 ответов


  • 841 рейтинг

    public static readonly поля немного необычны; public static свойства (только с get) будет более распространенным (возможно, при поддержке поля private static readonly).

    const значения записываются непосредственно в сайт вызова; это обоюдоострый:

    • бесполезно, если значение выбирается во время выполнения, возможно, из конфигурации
    • Если вы измените значение const, вам нужно перестроить все клиенты
    • , но это может быть быстрее, так как избегает вызова метода. , ,
    • . , , который иногда мог быть вставлен JIT в любом случае

    Если значение никогда не изменится на , то с константой все в порядке - Zero и т. Д. Дают разумные константы; p Кроме этого, свойства static более распространены.

    ответ дан Marc Gravell, с репутацией 759786, 16.04.2009
  • 206 рейтинг

    Я бы использовал static readonly, если Consumer находится в другой сборке. Наличие const и Consumer в двух разных сборках - это хороший способ выстрелить себе в ногу .

    ответ дан Michael Stum, с репутацией 114054, 16.04.2009
  • 176 рейтинг

    Некоторые другие вещи

    const int

    • должен быть инициализирован
    • инициализация должна быть во время компиляции

    только для чтения

    • может использовать значение по умолчанию, без инициализации
    • Инициализация
    • может быть во время выполнения
    ответ дан Peter, с репутацией 27335, 16.04.2009
  • 157 рейтинг

    Это просто дополнение к другим ответам. Я не буду их повторять (сейчас четыре года спустя).

    Существуют ситуации, когда const и неконстантный имеют разную семантику. Например:

    const int y = 42;
    
    static void Main()
    {
      short x = 42;
      Console.WriteLine(x.Equals(y));
    }
    

    распечатывает True, тогда как:

    static readonly int y = 42;
    
    static void Main()
    {
      short x = 42;
      Console.WriteLine(x.Equals(y));
    }
    

    пишет False.

    Причина в том, что метод x.Equals имеет две перегрузки, одна из которых принимает short (System.Int16), а другая - object (System.Object). Теперь вопрос в том, применим ли один или оба к моему аргументу y.

    Когда y является константой времени компиляции (литералом), случай const, становится важным, что существует неявное преобразование из int в short при условии, что int является константой, и при условии, что компилятор C # подтвердил что его значение находится в диапазоне short (что составляет 42). См. Неявные преобразования константных выражений в Спецификации языка C #. Таким образом, обе перегрузки должны быть учтены. Перегрузка Equals(short) является предпочтительной (любой short является object, но не все object являются short). Таким образом, y преобразуется в short, и эта перегрузка используется. Затем Equals сравнивает два short одинакового значения, и это дает true.

    Когда y не является константой, неявное неявное преобразование из int в short не существует. Это потому, что в целом int может быть слишком большим, чтобы поместиться в short. ( явное преобразование действительно существует, но я не сказал Equals((short)y), так что это не имеет значения. ) Мы видим, что применяется только одна перегрузка, Equals(object). Таким образом, y в штучной упаковке object. Затем Equals будет сравнивать System.Int16 с System.Int32, и поскольку типы времени выполнения даже не согласуются, это даст false.

    Мы заключаем, что в некоторых (редких) случаях изменение элемента типа const на поле static readonly (или другой способ, когда это возможно) может изменить поведение программы.

    ответ дан Jeppe Stig Nielsen, с репутацией 41844, 11.09.2013
  • 83 рейтинг

    Стоит отметить, что const ограничен типами примитивов / значений (исключение составляют строки)

    ответ дан Chris S, с репутацией 48915, 16.04.2009
  • 23 рейтинг

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

    .

    Краткая и понятная ссылка на MSDN здесь

    ответ дан yazanpro, с репутацией 1726, 14.11.2012
  • 17 рейтинг

    Статическая только для чтения : Значение может быть изменено через конструктор static во время выполнения. Но не через функцию члена.

    Константа : По умолчанию static. Значение не может быть изменено из любого места (Ctor, Function, время выполнения и т. Д. Не где).

    Только чтение : Значение может быть изменено через конструктор во время выполнения. Но не через функцию члена.

    Вы можете посмотреть мое репо: C # типы недвижимости .

    ответ дан Yeasin Abedin Siam, с репутацией 771, 12.01.2016
  • 13 рейтинг

    , const и readonly похожи, но они не совсем одинаковы.

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

    Например, const членов могут быть использованы для определения таких членов, как:

    struct Test
    {
        public const double Pi = 3.14;
        public const int Zero = 0;
    }
    

    Так как значения как 3. 14 и 0 - константы времени компиляции. Тем не менее, рассмотрим случай, когда вы определяете тип и хотите предоставить некоторые заранее созданные экземпляры этого типа. E. г. Вы можете определить класс Color и предоставить «константы» для общих цветов, таких как черный, белый и т. д. Это невозможно сделать с помощью констант, так как правые части не являются константами времени компиляции. Это можно сделать с помощью обычных статических членов:

    public class Color
    {
        public static Color Black = new Color(0, 0, 0);
        public static Color White = new Color(255, 255, 255);
        public static Color Red   = new Color(255, 0, 0);
        public static Color Green = new Color(0, 255, 0);
        public static Color Blue  = new Color(0, 0, 255);
        private byte red, green, blue;
    
        public Color(byte r, byte g, byte b) => (red, green, blue) = (r, g, b);
    }
    

    Но тогда ничто не может помешать клиенту Color сделать это, возможно, путем замены значений Black и White. Излишне говорить, что это вызвало бы смятение у других клиентов класса Color. Функция «только для чтения» предназначена для этого сценария.

    Просто вводя ключевое слово readonly в объявлениях, мы сохраняем гибкую инициализацию, предотвращая приглушение кода клиента.

    public class Color
    {
        public static readonly Color Black = new Color(0, 0, 0);
        public static readonly Color White = new Color(255, 255, 255);
        public static readonly Color Red   = new Color(255, 0, 0);
        public static readonly Color Green = new Color(0, 255, 0);
        public static readonly Color Blue  = new Color(0, 0, 255);
        private byte red, green, blue;
    
        public Color(byte r, byte g, byte b) => (red, green, blue) = (r, g, b);
    }
    

    Интересно отметить, что члены-константы всегда являются статическими, тогда как член только для чтения может быть статическим или нет, как обычное поле.

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

    public class A
    {
        public static const C = 0;
    }
    

    и другой разработчик написал код, который полагался на A:

    public class B
    {
        static void Main() => Console.WriteLine(A.C);
    }
    

    Теперь можно ли сгенерированный код полагаться на тот факт, что А. C является постоянной времени компиляции? Я. е. , может использование А. C просто заменить на значение 0? Если вы скажете «да» на это, то это означает, что разработчик A не может изменить способ, которым A. C инициализирован - это связывает руки разработчика A без разрешения.

    Если вы ответите «нет» на этот вопрос, то важная оптимизация будет пропущена. Возможно, автор А уверен, что А. С всегда будет ноль. Использование как const, так и readonly позволяет разработчику A указать намерение. Это улучшает поведение при управлении версиями, а также повышает производительность.

    ответ дан Ramesh Rajendran, с репутацией 17575, 28.09.2013
  • 11 рейтинг

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

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

    ответ дан Peter Meyer, с репутацией 20656, 16.04.2009
  • 6 рейтинг

    Const: Const - это не что иное, как «константа», переменная, значение которой является постоянным, но во время компиляции. И обязательно присвоить ему значение. По умолчанию const является статическим, и мы не можем изменить значение переменной const во всей программе.

    Static ReadOnly: Значение переменной типа Static Readonly может быть назначено во время выполнения или назначено во время компиляции и изменено во время выполнения. Но значение этой переменной можно изменить только в статическом конструкторе. И не может быть изменено в дальнейшем. Это может измениться только один раз во время выполнения

    Ссылка: c-sharpcorner

    ответ дан mayank, с репутацией 1629, 9.09.2013
  • 6 рейтинг

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

    Например, предположим, что сборка X предоставляет постоянную следующим образом:

    public const decimal ProgramVersion = 2.3;
    

    Если сборка Y ссылается на X и использует эту константу, значение 2. 3 будет запечен в сборке Y при компиляции. Это означает, что если X позднее перекомпилируется с константой 2. 4, Y все равно используйте старое значение 2. 3 до Y перекомпилируется. Статический Поле readonly позволяет избежать этой проблемы.

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

    ответ дан Yagnesh Cangi, с репутацией 128, 7.04.2015
  • 3 рейтинг

    const:

    1. значение должно быть указано в декларации
    2. постоянная времени компиляции

    только для чтения:

      Значение
    1. может быть дано при объявлении или во время выполнения с использованием конструкторов. Значение может варьироваться в зависимости от используемого конструктора.
    2. постоянная времени выполнения
    ответ дан dasumohan89, с репутацией 63, 11.12.2013
  • 2 рейтинг

    Существует небольшая разница между полями const и static readonly в C #. Чистый

    const должен быть инициализирован значением во время компиляции.

    const по умолчанию является статическим и должен быть инициализирован постоянным значением, которое не может быть изменено позже. Его нельзя использовать со всеми типами данных. Для экс-DateTime. Его нельзя использовать с типом данных DateTime.

    public const DateTime dt = DateTime.Today;  //throws compilation error
    public const string Name = string.Empty;    //throws compilation error
    public static readonly string Name = string.Empty; //No error, legal
    

    только для чтения может быть объявлено как статическое, но не обязательно. Не нужно инициализировать во время объявления. Его значение может быть присвоено или изменено с помощью конструктора один раз. Таким образом, существует возможность один раз изменить значение поля только для чтения (не имеет значения, статическое оно или нет), что невозможно с помощью const.

    ответ дан Chirag, с репутацией 2696, 15.12.2014
  • 1 рейтинг

    Константы, как следует из названия, поля, которые не изменяются и обычно определяются статически во время компиляции в коде.

    Переменные только для чтения - это поля, которые могут изменяться при определенных условиях.

    Они могут быть инициализированы, когда вы впервые объявляете их как константу, но обычно они инициализируются во время конструирования объекта внутри конструктора.

    Они не могут быть изменены после инициализации в условиях, указанных выше.

    Статический только для чтения звучит для меня как плохой выбор, поскольку, если он статический и никогда не меняется, просто используйте его public const, если он может измениться, то он не является константой, а затем, в зависимости от ваших потребностей, вы можете использовать только для чтения или просто обычная переменная.

    Кроме того, еще одно важное отличие состоит в том, что константа принадлежит классу, а переменная только для чтения принадлежит экземпляру!

    ответ дан Claudiu Cojocaru, с репутацией 24, 21.11.2016
  • 0 рейтинг

    Const : значения переменных const должны определяться вместе с объявлением и после него не изменится const неявно статичны, поэтому без создания экземпляра класса мы можем получить к ним доступ. это имеет значение во время компиляции

    ReadOnly : доступные только для чтения значения переменных, которые мы можем определить при объявлении, а также при использовании конструктора во время выполнения. переменные только для чтения не могут получить доступ без экземпляра класса.

    Статическое чтение только : статические переменные значения только для чтения, которые мы можем определить при объявлении, а также только через статический конструктор, но не с любым другим конструктором. Эти переменные также мы можем получить без создания экземпляра класса (как статические переменные).

    static readonly будет лучшим выбором, если мы будем использовать переменные в разных сборках. Пожалуйста, проверьте полную информацию ниже ссылка

    https: // www. виноградное сусло. de / 2009/01/14 / const-strings-a-очень удобный способ выстрелить себе в ногу /

    ответ дан user1756922, с репутацией 54, 27.09.2018