c# - разница - чем отличаются константы и поля, доступные только для чтения




В чем разница между константой и readonly? (20)

В чем разница между const и readonly и вы используете ее над другой?


Константы

  • Константы по умолчанию статичны
  • Они должны иметь значение во время компиляции (вы можете иметь, например, 3.14 * 2, но не можете вызывать методы)
  • Может быть объявлено в рамках функций
  • Скопируются в каждую сборку, которая их использует (каждая сборка получает локальную копию значений)
  • Может использоваться в атрибутах

Поля экземпляров Readonly

  • Должен иметь установленное значение, к тому времени, когда конструктор завершает работу
  • Оцениваются при создании экземпляра

Статические поля readonly

  • Оцениваются, когда выполнение кода попадает в ссылку на класс (когда создается новый экземпляр или выполняется статический метод)
  • Должно быть оцененное значение к моменту завершения статического конструктора
  • Не рекомендуется помещать ThreadStaticAttribute в эти (статические конструкторы будут выполняться только в одном потоке и будут устанавливать значение для его потока, все остальные потоки будут иметь это значение неинициализированным)

ПОСТ

  1. Ключевое слово const может применяться к полям или локальным переменным
  2. Мы должны назначить поле const во время объявления
  3. Нет выделенной памяти. Поскольку значение const встроено в код IL после компиляции. Это похоже на обнаружение всех вхождений переменной const и замену на ее значение. Таким образом, код IL после компиляции будет иметь жестко заданные значения вместо константных переменных
  4. Константа в C # по умолчанию статична.
  5. Значение является постоянным для всех объектов
  6. Существует проблема с версией dll - это означает, что всякий раз, когда мы меняем общедоступную константу или свойство (на самом деле это теоретически не предполагается), любая другая dll или сборка, использующая эту переменную, должна быть перестроена
  7. Только встроенные типы C # могут быть объявлены как постоянные
  8. Поле Const не может быть передано как параметр ref или out

ReadOnly

  1. Ключевое слово readonly применяется только к полям, а не к локальным переменным
  2. Мы можем назначить поле readonly во время объявления или в конструкторе, а не в каких-либо других методах.
  3. динамическая память, выделенная для полей readonly, и мы можем получить значение во время выполнения.
  4. Readonly принадлежит к объекту, созданному таким образом доступным только через экземпляр класса. Чтобы сделать его членом класса, нам нужно добавить статическое ключевое слово перед чтением.
  5. Значение может быть различным в зависимости от используемого конструктора (поскольку он относится к объекту класса)
  6. Если вы объявляете не-примитивные типы (ссылочный тип), поскольку только для чтения только ссылка является неизменной, а не объектом, который она содержит.
  7. Поскольку значение получено во время выполнения, нет проблемы с версией dll с полями / свойствами readonly.
  8. Мы можем передать поле readonly в качестве параметров ref или out в контексте конструктора.

ReadOnly: значение будет инициализировано только один раз из конструктора класса.
const: может быть инициализирована в любой функции, но только один раз


В принципе; вы можете присвоить значение статическому полю readonly неизменному значению во время выполнения, тогда как константе должно быть присвоено постоянное значение.


Еще есть.

Поскольку const действительно работает только с базовыми типами данных, если вы хотите работать с классом, вы можете почувствовать «принудительное» использование ReadOnly. Однако остерегайтесь ловушки! ReadOnly означает, что вы не можете заменить объект другим объектом (вы не можете заставить его ссылаться на другой объект). Но любой процесс, который имеет ссылку на объект, может свободно изменять значения внутри объекта!

Поэтому не следует путать, думая, что ReadOnly подразумевает, что пользователь не может ничего изменить. В C # нет простого синтаксиса, чтобы предотвратить изменение экземпляра класса из-за изменения его внутренних значений (насколько я знаю).



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

В качестве упражнения попробуйте создать внешнюю библиотеку и использовать ее в консольном приложении, затем измените значения в библиотеке и перекомпилируйте ее (без перекомпиляции потребительской программы), отбросьте DLL в каталог и запустите EXE вручную, вы должны найти что постоянная строка не изменяется.


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


Одно можно добавить к тому, что люди сказали выше. Если у вас есть сборка, содержащая значение readonly (например, только для чтения MaxFooCount = 4;), вы можете изменить значение, которое вызывает вызовы сборок, отправив новую версию этой сборки с другим значением (например, только для чтения MaxFooCount = 5;)

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

Если вы достигли уровня владения C #, вы готовы к книге Билла Вагнера «Эффективный C #: 50 конкретных способов улучшить ваш C #». Ответы на этот вопрос подробно (и еще 49 вещей).


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

Пример:

public static class Text {
  public const string ConstDescription = "This can be used.";
  public readonly static string ReadonlyDescription = "Cannot be used.";
}

public class Foo 
{
  [Description(Text.ConstDescription)]
  public int BarThatBuilds {
    { get; set; }
  }

  [Description(Text.ReadOnlyDescription)]
  public int BarThatDoesNotBuild {
    { get; set; }
  }
}

Помимо очевидной разницы

  • обязательство объявить значение во время определения для readonly значений readonly VS может быть вычислено динамически, но должно быть назначено до того, как конструктор завершит работу .. после этого он будет заморожен.
  • «const» неявно static . Для доступа к ним используется нотация ClassName.ConstantName .

Существует тонкая разница. Рассмотрим класс, определенный в AssemblyA .

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly int I_RO_VALUE;
  public Const_V_Readonly()
  {
     I_RO_VALUE = 3;
  }
}

AssemblyB ссылается на AssemblyA и использует эти значения в коде. Когда это скомпилировано,

  • в случае значения const это похоже на find-replace, значение 2 «запекается» в IL AssemblyB . Это означает, что если завтра я буду обновлять I_CONST_VALUE до 20 в будущем. AssemblyB все равно будет 2, пока я не перекомпиляю его .
  • в случае значения readonly это похоже на ref на ячейку памяти. Значение не запекается в IL-ов AssemblyB . Это означает, что, если местоположение памяти обновлено, AssemblyB получает новое значение без перекомпиляции. Поэтому, если I_RO_VALUE обновлен до 30, вам нужно только собрать AssemblyA . Все клиенты не нуждаются в повторной компиляции.

Поэтому, если вы уверены, что значение константы не изменится, используйте константу.

public const int CM_IN_A_METER = 100;

Но если у вас есть константа, которая может измениться (например, точность) или если вы сомневаетесь, используйте readonly .

public readonly float PI = 3.14;

Обновление: Аку нужно получить упоминание о том, что он указал на это в первую очередь. Также мне нужно подключить, где я это узнал. Эффективный C # - Билл Вагнер


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

public class MyClass
{
    public const double PI1 = 3.14159;
}

Член readonly подобен константе в том, что он представляет неизменное значение. Разница в том, что член readonly может быть инициализирован во время выполнения, в конструкторе, а также может быть инициализирован по мере их объявления.

public class MyClass1
{
     public readonly double PI2 = 3.14159;

     //or

     public readonly double PI3;

     public MyClass2()
     {
         PI3 = 3.14159;
     }
}

Const

  • Они не могут быть объявлены как static (они неявно статичны)
  • Значение константы оценивается во время компиляции
  • константы инициализируются только при объявлении

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

  • Они могут быть либо на уровне экземпляра, либо на статическом
  • Значение оценивается во время выполнения
  • readonly может быть инициализирован в декларации или кодом в конструкторе

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

Помните: для ссылочных типов в обоих случаях (статический и экземпляр) модификатор readonly только запрещает вам назначать новую ссылку на поле. Он специально не делает неизменным объект, на который указывает ссылка.

Для получения дополнительной информации см. Часто задаваемые вопросы C # по этой теме: http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx


Существует заметная разница между полями const и readonly в C # .Net

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

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

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

class A
{
    public readonly int Id;

    public A(int i)
    {
        Id = i;
    }
}

Затем поле readonly может быть инициализировано мгновенными конкретными значениями следующим образом:

A objOne = new A(5);
A objTwo = new A(10);

Здесь экземпляр objOne будет иметь значение поля readonly как 5, а objTwo - 10. Это невозможно, используя const.


У меня есть сочленя! Если вы ссылаетесь на константу из другой сборки, ее значение будет скомпилировано прямо в вызывающую сборку. Таким образом, когда вы обновляете константу в указанной сборке, она не изменится в вызывающей сборке!


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


Вот еще одна ссылка, демонстрирующая, как const не является безопасным версией или релевантным для ссылочных типов.

Резюме :

  • Значение вашего свойства const устанавливается во время компиляции и не может меняться во время выполнения
  • Константа не может быть помечена как статическая - ключевое слово обозначает, что они являются статическими, в отличие от полей readonly, которые могут.
  • Const не может быть ничего, кроме значений (примитивных) типов
  • Ключевое слово readonly помечает поле как неизменяемое. Однако свойство может быть изменено внутри конструктора класса
  • Ключевое слово только для чтения можно также комбинировать со статикой, чтобы заставить его действовать так же, как const (по крайней мере на поверхности). Существует заметная разница, когда вы смотрите на IL между двумя
  • константные поля помечены как «буквальные» в IL, а readonly - «initonly»,

const : не может быть изменен нигде.

readonly : Это значение может быть изменено только в конструкторе. Не может быть изменен в обычных функциях.


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

Константа : по умолчанию статична. Значение не может быть изменено нигде (Ctor, Function, runtime etc no-where)


постоянная

Мы должны указать значение в поле const, когда оно определено. Затем компилятор сохраняет значение константы в метаданных сборки. Это означает, что константа может быть определена только для примитивного типа, такого как boolean, char, byte и т. Д. Константы всегда считаются статическими членами, а не членами экземпляра.

Readonly

Поля Readonly могут быть разрешены только во время выполнения. Это означает, что мы можем определить значение для значения, используя конструктор для типа, в котором объявлено поле. Проверка выполняется компилятором, что поля readonly не записываются каким-либо другим способом, кроме конструктора.

Подробнее об обоих объясненных здесь в этой статье





readonly