В чем разница между const
и readonly
в C#?
В каких случаях можно использовать одно вместо другого?
Кроме очевидной разницы
Есть тонкое различие. Считайте класс определенным в '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' и использование эти ценности в кодексе. Когда это собрано,
Таким образом, если Вы уверены что ценность постоянного won' t изменение используют 'константу'.
public const int CM_IN_A_METER = 100;
Но если у Вас есть константа, которая может измениться (например, w.r.t. точность).. или когда в сомнении, используйте 'только для чтения'.
public readonly float PI = 3.14;
Обновление: Aku должен получить упоминание, потому что он указал на это сначала. Также я должен включиться, где я изучил это.. Эффективный C# - Билл Вагнер
Есть gotcha с consts! Если Вы сошлетесь на константу от другого собрания, его стоимость будет собрана прямо в собрание запроса. Тот путь, когда Вы обновляете константу на собрании, на которое ссылаются, это won' t изменяются на собрании запроса!
Только, чтобы добавить, ReadOnly для справки печатает, только делает ссылку, только для чтения не ценности. Например:
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};
public UpdateReadonly()
{
I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
I_RO_VALUE = new char[]{'V'}; //will cause compiler error
}
}
Это объясняет это. Резюме: const должна быть инициализирована во время объявления, readonly может быть инициализирована в конструкторе (и, следовательно, иметь различное значение в зависимости от используемого конструктора).
EDIT: О тонком различии см. выше Gishu'gotcha
Есть маленький gotcha с только для чтения. Область только для чтения может быть установлена многократно в конструкторе (конструкторах). Даже если значение установлено в двух различных цепочечных конструкторах, оно все еще позволено.
< pre> < code> общественный Образец класса { частная последовательность только для чтения ro;public Sample() {
ro = "set";
}
public Sample(string value) : this() {
ro = value; // this works even though it was set in the no-arg ctor
}
}
Постоянный участник определен во время компиляции и не может быть изменен во времени выполнения. Константы объявлены как область, используя ключевое слово 'константы' и должны быть инициализированы, как они объявлены.
public class MyClass
{
public const double PI1 = 3.14159;
}
Участник 'только для чтения' похож на константу в этом, она представляет неизменную стоимость. Различие - то, что участник 'только для чтения' может быть инициализирован во времени выполнения, в конструкторе, также способность, которая будет инициализирована, поскольку они объявлены.
public class MyClass1
{
public readonly double PI2 = 3.14159;
//or
public readonly double PI3;
public MyClass2()
{
PI3 = 3.14159;
}
}
константа
только для чтения
const - это константа времени компиляции, в то время как readonly позволяет вычислить значение во время выполнения программы и установить его в конструкторе или инициализаторе поля. Таким образом, значение 'const' всегда является константой, а значение 'readonly' после его присвоения становится доступным только для чтения.
1рик Липперт (Eric Lippert)1 из команды разработчиков C# дает более подробную информацию о различных типах неизменяемости
Here' s другая связь демонстрация, как константа isn' t безопасная версия, или важная для справочных типов.
Резюме :
Читайте Только : Стоимость может быть изменена через Ctor во времени выполнения. Но не через членскую Функцию
Постоянный : Статичным defult. Стоимость не может быть изменена ниоткуда (Ctor, Функция, время выполнения и т.д. нигде)
Еще один gotcha: ценности только для чтения могут быть изменены " devious" кодекс через отражение.
var fi = this.GetType()
.BaseType
.GetField("_someField",
BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);
[Я могу изменить частную унаследованную область только для чтения в C#, используя отражение?] [1] [1]: https://stackoverflow.com/questions/1401458/can-i-change-a-private-readonly-inherited-field-in-c-using-reflection/1401499#14014 99
Я полагаю, что значение const
одинаково для всех объектов (и должно инициализироваться литеральным выражением), в то время как readonly
может быть разным для каждого инстанса...
Один из членов команды в нашем офисе обеспечил следующее руководство на том, когда использовать константу, статичную, и только для чтения:
Одно заключительное примечание: область константы статична, но инверсия не верна.
Они оба постоянные, но константа доступна также во время компиляции. Это означает, что один аспект различия - то, что Вы можете использовать переменные константы в качестве входа, чтобы приписать конструкторов, но не переменные только для чтения.
Пример:
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; }
}
}
Отмеченная константа переменных немного больше, чем сильно напечатана #define макрос, во время компиляции ссылки переменной константы заменены действующими буквальными ценностями. Как следствие только определенные встроенные примитивные типы стоимости могут использоваться таким образом. Переменные отметили только для чтения, может быть установлен, в конструкторе, во времени выполнения, и их только для чтения проведено в жизнь во время времени выполнения также. Есть некоторая незначительная исполнительная стоимость, связанная с этим, но это означает, что Вы можете использовать только для чтения с любым типом (даже справочные типы).
Кроме того, переменные константы неотъемлемо статичны, тогда как переменные только для чтения могут быть случаем, конкретным при желании.
Есть заметные различия между константой и областями только для чтения в C#.Net
константа по умолчанию статична и должна быть инициализирована с постоянной величиной, которая не может быть изменена позже. Изменение стоимости не позволено в конструкторах, также. Это не может использоваться со всеми типами данных. Для экс-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
только для чтения может быть объявлен как статичный, но не необходимым. Никакая потребность инициализировать во время декларации. Его стоимость может быть назначена или изменила конструктора использования. Так, это дает преимущество, когда используется в качестве участника класса случая. У двух различных экземпляров может быть различная ценность области только для чтения. Поскольку исключая -
class A
{
public readonly int Id;
public A(int i)
{
Id = i;
}
}
Тогда область только для чтения может быть инициализирована с мгновенными определенными ценностями, следующим образом:
A objOne = new A(5);
A objTwo = new A(10);
Здесь, у случая objOne будет ценность области только для чтения как 5, и objTwo имеет 10. Который не является возможной константой использования.
Другой < I> gotcha.< P> Так как константа действительно только работает с типами основных данных, если Вы хотите работать с классом, Вы можете чувствовать " forced" использовать ReadOnly. Однако остерегайтесь ловушки! ReadOnly подразумевает, что Вы не можете заменить объект другим объектом (Вы can' t заставляют его относиться к другому объекту). Но любой процесс, у которого есть ссылка на объект, бесплатный изменить ценности < B> < I> inside объект! < P> Так don' t быть перепутанным в размышление, что ReadOnly подразумевает пользователя can' t изменяют вещи. Нет никакого простого синтаксиса в C#, чтобы препятствовать экземпляру класса изменение его внутренних ценностей (насколько я знаю).
Постоянный
Мы должны предоставить стоимость области константы, когда это определено. Компилятор тогда экономит стоимость константы в метаданных собрания. Это означает, что константа может быть определена только для примитивного типа как булев, случайная работа, байт и так далее. Константы всегда считают статическими участниками, не участниками случая.
Только для чтения
Области только для чтения могут только быть решены во времени выполнения. Это означает, что мы можем определить стоимость для стоимости, используя конструктора для типа, в котором объявлена область. Проверка сделана компилятором, что области только для чтения не написаны никаким методом кроме конструктора.
Больше об обоих объясненный здесь в этой статье