Яка різниця між const
і readonly
в C #?
Коли б ви використовували одне над іншим?
Яка різниця між const
і readonly
в C #?
Коли б ви використовували одне над іншим?
Відповіді:
Крім очевидної різниці
const
VS, readonly
можна обчислити динамічно, але їх потрібно призначити до виходу конструктора .. після цього його заморожують.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
значення, це як пошук-заміна, значення 2 "випікається" в AssemblyB
ІЛ. Це означає, що якщо завтра я I_CONST_VALUE
в майбутньому оновлю до 20. AssemblyB
ще 2, поки я не перекомпілюю його .readonly
значення це як місце ref
в пам'яті. Значення не записується в AssemblyB
Іл. Це означає, що якщо місце пам'яті оновлено, воно AssemblyB
отримує нове значення без перекомпіляції. Тож якщо I_RO_VALUE
оновлено до 30, потрібно лише будувати AssemblyA
. Усі клієнти не потрібно перекомпілювати.Тож якщо ви впевнені, що значення константи не зміниться, використовуйте a const
.
public const int CM_IN_A_METER = 100;
Але якщо у вас є константа, яка може змінюватися (наприклад, точність роботи) .. або коли виникаєте сумніви, використовуйте a readonly
.
public readonly float PI = 3.14;
Оновлення: Аку потрібно згадати, адже він спочатку це зазначив. Також мені потрібно підключити те, де я це навчився. Ефективний C # - Білл Вагнер
static
Точка , здається, самий важливий і корисний пункт -consts are implicitly static
readonly
змінні можуть бути змінені поза конструктором (відображення). Лише компілятор намагається перешкодити вам змінювати var поза конструктором.
readonly
змінні mini-me не можна змінювати після закінчення конструктора, навіть через відображення. Час виконання цього не виконує. Виконавча також відбувається не застосовувати , що ви не змінити string.Empty
до "Hello, world!"
, але я до сих пір не буду стверджувати , що це робить string.Empty
змінним, або що код не повинен припускати , що string.Empty
завжди буде рядком нульової довжини.
Є ґутча з consts! Якщо ви посилаєтесь на константу з іншої збірки, її значення буде скомпільовано прямо у виклику. Таким чином, коли ви оновлюєте константу у посиланні на збірку, вона не змінюватиметься у виклику!
Додамо лише, що 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
}
}
string
той, який ви могли б використовувати як постійну?
const
типи посилань, крім рядка, але константа може мати лише значення null
.
Це пояснює це . Короткий зміст: const повинен бути ініціалізований під час оголошення, він може бути ініціалізований на конструкторі (і, таким чином, мати інше значення залежно від конструктора, який використовується).
РЕДАКТУВАННЯ: Дивіться дивовижну приналежність Гішу вище про тонку різницю
Існує невеликий готча з лише читанням. Поле для читання може бути встановлено кілька разів у межах конструкторів. Навіть якщо значення встановлено у двох різних ланцюгових конструкторах, все одно це дозволено.
public class Sample {
private readonly string ro;
public Sample() {
ro = "set";
}
public Sample(string value) : this() {
ro = value; // this works even though it was set in the no-arg ctor
}
}
Постійний член визначається під час компіляції і не може бути змінений під час виконання. Константи оголошуються як поле з використанням 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
(вони неявно статичні)лише для читання
static const int i = 0;
const
декларації не можна робити всередині методів?
Конст - це константа часу компіляції, тоді як зчитування дозволяє лише обчислювати значення під час виконання та встановлювати в ініціалізаторі конструктора або поля. Отже, "const" завжди постійний, але "readlyly" читається лише після його призначення.
Ерік Ліпперт із команди C # має більше інформації про різні типи незмінності
Ось ще одне посилання, що демонструє, наскільки const не є безпечним для версії, чи релевантним для референтних типів.
Підсумок :
Тільки для читання : значення можна змінювати через Ctor під час виконання. Але не через функцію члена
Постійний : За допомогою статичної дефолтності. Значення не можна змінювати з будь-якого місця (Ctor, Function, час виконання тощо. Ні-де)
Ще одна проблема: значення лише для читання можна змінити за допомогою "хибного" коду за допомогою відображення.
var fi = this.GetType()
.BaseType
.GetField("_someField",
BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);
Чи можу я змінити приватне спадкове поле для читання в C # за допомогою відображення?
Я вважаю, що const
значення однакове для всіх об'єктів (і має бути ініціалізовано буквальним виразом), тоді як readonly
може бути різним для кожної інстанції ...
Один з членів команди в нашому офісі надав наступні вказівки щодо використання const, static та readonly:
Останнє зауваження: поле const є статичним, але обернене не відповідає дійсності.
Вони обидва постійні, але const доступний і під час компіляції. Це означає, що одним із аспектів різниці є те, що ви можете використовувати const змінні як вхідні дані для конструкторів атрибутів, але не змінні лише для читання.
Приклад:
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; }
}
}
коли використовувати const
абоreadonly
const
readonly
App.config
, але як тільки вона ініціалізується, її неможливо змінитиЗмінні, позначені const, трохи більше, ніж сильно набрані #define макроси, під час компіляції посилання змінних const замінюються вбудованими буквальними значеннями. Як наслідок, таким чином можна використовувати лише певні вбудовані примітивні типи значень. Змінні, позначені лише для читання, можна встановлювати в конструкторі під час виконання, і їх необхідність лише для читання застосовується і під час виконання. З цим пов'язана незначна вартість продуктивності, але це означає, що ви можете використовувати лише для читання лише з будь-яким типом (навіть із типовими типами).
Крім того, змінні const за своєю суттю є статичними, тоді як змінні, що читаються тільки, за бажанням можуть бути конкретними.
Ще одна гатча .
Оскільки const дійсно працює лише з базовими типами даних, якщо ви хочете працювати з класом, ви можете відчувати себе «змушеним» використовувати ReadOnly. Однак остерігайтеся пастки! ReadOnly означає, що ви не можете замінити об'єкт іншим об'єктом (ви не можете змусити його посилатися на інший об’єкт). Але будь-який процес, який має посилання на об'єкт, вільний для зміни значень всередині об'єкта!
Тому не слід плутати думку про те, що ReadOnly означає, що користувач не може змінити речі. У C # не існує простого синтаксису, який би запобігав зміні внутрішніх значень класу (наскільки я знаю).
Існує помітна різниця між полями const і readonly в C # .Net
const за замовчуванням статичний і його потрібно ініціалізувати постійним значенням, яке згодом неможливо змінити. Зміна значення також не дозволяється в конструкторах. Його не можна використовувати з усіма типами даних. Для колишнього 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. Що неможливо за допомогою const.
Константа буде зібрана у споживача як буквальне значення, тоді як статична рядок слугуватиме посиланням на визначене значення.
Як вправу спробуйте створити зовнішню бібліотеку та споживати її в консольному додатку, потім змініть значення в бібліотеці та перекомпілюйте її (не перекомпілюючи споживчу програму), опустіть DLL у каталог та запустіть EXE вручну, ви повинні знайти що постійний рядок не змінюється.
Постійний
Нам потрібно надати значення поля const, коли воно визначене. Потім компілятор зберігає значення константи в метаданих збірки. Це означає, що константа може бути визначена лише для примітивного типу, наприклад, булева, char, байт тощо. Константи завжди вважаються статичними членами, а не членами екземплярів.
Лише для читання
Поля для читання лише можна вирішити лише під час виконання. Це означає, що ми можемо визначити значення для значення, використовуючи конструктор для типу, в якому оголошено поле. Перевірка проводиться компілятором, що поля, які читаються тільки не записуються іншим способом, крім конструктора.
Більше про обидва пояснено тут у цій статті
Const і readonly схожі, але вони не зовсім однакові. Поле const - це константа часу компіляції, тобто це значення може бути обчислено під час компіляції. Поле для читання дає змогу отримати додаткові сценарії, коли деякий код повинен бути запущений під час побудови типу. Після побудови поле для читання тільки не може бути змінено.
Наприклад, члени const можуть використовуватися для визначення членів типу:
struct Test
{
public const double Pi = 3.14;
public const int Zero = 0;
}
оскільки значення, такі як 3.14 і 0, є константами часу компіляції. Однак розглянемо випадок, коли ви визначаєте тип і хочете надати деякі його попередні файли. Наприклад, ви можете визначити клас кольорів та надати "константи" для таких кольорів, як чорний, білий та ін. Це неможливо зробити з членами const, оскільки права сторона не є константами часу компіляції. Це можна зробити за допомогою регулярних статичних членів:
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 = r;
green = g;
blue = b;
}
}
але тоді немає нічого, що не дозволяє клієнту Color не спілкуватися з ним, можливо, замінюючи значення Чорно-Біле. Зайве говорити, що це може викликати побоювання у інших клієнтів класу Color. Функція "лише для читання" стосується цього сценарію. Просто вводячи в декларації ключове слово, що читається лише ми, ми зберігаємо гнучку ініціалізацію, не дозволяючи клієнтському коду вимикатись.
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 = r;
green = g;
blue = b;
}
}
Цікаво відзначити, що члени const завжди є статичними, тоді як член, що читає лише, може бути статичним чи ні, як звичайне поле.
Можна використовувати одне ключове слово для цих двох цілей, але це призводить до проблем з версіями або до продуктивності. Припустимо на мить, що для цього ми використовували одне ключове слово (const), і розробник написав:
public class A
{
public static const C = 0;
}
і інший розробник написав код, який спирався на A:
public class B
{
static void Main() {
Console.WriteLine(A.C);
}
}
Тепер, чи може сформований код покладатися на той факт, що AC - константа часу компіляції? Тобто, чи може використання змінного струму просто замінити значенням 0? Якщо ви скажете "так" цьому, це означає, що розробник A не може змінити спосіб ініціалізації AC - це пов'язує руки розробника з A без дозволу. Якщо ви скажете "ні" на це питання, важлива оптимізація пропущена. Можливо, автор A впевнений, що зміна струму завжди буде дорівнює нулю. Використання const і readonly дозволяє розробнику A вказати наміри. Це сприяє кращій поведінці версій, а також кращій роботі.
Різниця полягає в тому, що значення статичного поля лише для читання встановлюється під час виконання, тому воно може мати різне значення для різних виконань програми. Однак значення поля const встановлюється константа часу компіляції.
Пам’ятайте: Для типів посилань в обох випадках (статичний і екземпляр) модифікатор, що читає лише, не дозволяє вам призначити нове посилання на поле. Це спеціально не робить непорушним об'єкт, на який вказується посилання.
Для детальної інформації зверніться до C # Запитання на цю тему: http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx
Постійні змінні оголошуються та ініціалізуються під час компіляції. Значення неможливо змінити після підопічних. Змінні лише для читання будуть ініціалізовані лише із конструктора Static класу. Тільки для читання використовується лише тоді, коли ми хочемо призначити значення під час виконання.
Const : Абсолютне постійне значення протягом життя програми.
Readonly : Це може бути змінено за часом роботи.
Одне додати до того, що люди сказали вище. Якщо у вас є збірка, що містить значення для читання тільки (наприклад, для readonly MaxFooCount = 4;), ви можете змінити значення, яке бачать викликові збірки, доставляючи нову версію цієї збірки з іншим значенням (наприклад, лише для читання MaxFooCount = 5;)
Але з const, він буде складений в код абонента, коли абонент був складений.
Якщо ви досягли цього рівня кваліфікації на C #, ви готові до книги Білла Вагнера "Ефективний C #: 50". Спеціальні способи поліпшити свій C #, який детально відповідає на це питання (та 49 інших речей).