Кто не сомневается, когда начинает узнавать что-то новое? 🤔
Весь мир
В этом случае, когда кто-то начинает программировать в .NET, он обычно получает вопросы, на которые даже многие старшие разработчики не знают, как правильно ответить:
В чем разница между READONLY и CONST?
Они одинаковые?
Если предполагается переменная, которую можно только читать, но нельзя изменять… Можно ли применить к ней определение константы?
Отвечаю вам:
NO ❌
Хорошо, но ... Если они не такие ... В чем их разница?
Что ж, начнем с основ:
Сначала они могут показаться одинаковыми, если мы примем во внимание, что результаты похожи, но мы должны понимать реальные различия между ними, поскольку, если мы не будем использовать их должным образом, у нас может быть много проблем в наших проектах.
1. Только чтение
Чтобы определить константу в C #, мы будем использовать это 👇
public const double PI = 3.14;
С помощью модификатора const мы сообщаем компилятору, что присваиваемая переменная будет константой. Таким образом, он может быть инициализирован только при объявлении.
Если мы захотим его изменить, компилятор скажет нам «нет» и покажет нам эту ошибку:
В случае определения переменной только для чтения это аналогично 👇
public readonly double PI = 3.14;
И снова, если мы попытаемся его изменить, он снова выдаст нам ошибку, но уже не ту:
✅ Заключение:
Хотя мы оба допустили ошибки, это не одно и то же. В этом случае разница в том, что классы, доступные только для чтения, МОГУТ быть изменены, только пока конструктор этого класса не выполняется.
Что я имел в виду?
Просто находясь внутри конструктора, мы можем изменить их, если мы хотим, например, получить их значение из параметров, которые мы передаем конструктору. И нет, это невозможно в случае константы.
2. Статические члены
Второе наиболее заметное отличие состоит в том, что константа ВСЕГДА является статическим членом класса, к которому она принадлежит.
Вернемся к практике, если мы напишем:
public class Class01{ public const double PI = 3.14;}
И затем мы пытаемся получить доступ к значению PI, не нужно было бы создавать новый объект класса, то есть 👇
Console.Write("The Pi value is " + Class01.PI);
Нам не нужно было бы создавать что-либо в любое время, поскольку мы являемся статическим членом, общим с другими объектами этого класса и явно существующим в его определении.
Если мы хотим сделать то же самое с переменной только для чтения, нам придется добавить модификатор static. Это выглядело бы так 👇
public class Class01{ public static readonly double PI = 3.14;}
Таким образом, мы могли бы использовать его так же, как константу.
3. Компиляция
На данный момент все ясно? 🤗
Я бы хотел, чтобы вы отреагировали 2 👏 (не 1, не 3) двумя хлопками. Таким образом, я смогу узнать, достаточно ли ясны мои объяснения, и, таким образом, смогу улучшить свои статьи. 😊
Теперь собираемся еще немного «покопаться».
Предположим, у нас есть базовый класс, определенный следующим образом:
using System; namespace ConstantTestLIB { Public class Class01 { Public static readonly double readonlyPI = 3.14; Public const double constantPI = 3.14; } }
По сути, как и в первом примере, мы определяем один класс с двумя статическими членами 👇
- Пи только для чтения
- Const Pi
Мы создаем .dll, чтобы использовать его в других приложениях.
Теперь мы создаем новый проект и добавляем ссылку на DLL, созданную ранее. И мы просто показываем результат на экране, как здесь:
using System; using ConstantTestLIB; namespace ConstantTestCMD { class Program { Static void Main (string[] args) { Console.WriteLine(“The constant is: ” + Class01.ConstantPI + “and the readonly is: ” + Class01.ReadOnlyPI); } } }
Если мы запустим это, результат будет 👇
Ладно, ладно, ладно?
Теперь представим, что мы компилируем и отправляем нашим клиентам новое консольное приложение.
Ой, подождите, значение PI больше… 😰
Хорошо, мы просто меняем код DLL, компилируем его и отправляем обратно в него 👍
Было бы просто необходимо перезаписать новую DLL старой, и все заработало бы без каких-либо проблем. Но ... Давайте снова запустим программу с новой DLL. Вы рухнете, как синий экран Windows 10👇
Было изменено только значение переменной только для чтения, а не константы.
Если мы исследуем сгенерированный код с помощью декомпилятора, мы найдем это 👇
Благодаря этому мы можем понять, что, даже если они являются членами класса, принадлежащего внешней DLL, константы компилируются буквально.
✅ Это ОЧЕНЬ просто объяснить:
Когда компилятор анализирует код и видит, что мы используем константу и ее нельзя изменить, он просто меняет ее на реальное значение со всех сторон, даже если мы компилируем это с внешней DLL.
В случае переменных только для чтения мы видим, что они все еще используются из DLL.
На этом мы подошли к основной проблеме, которую вы можете найти. Если вы объявляете переменную только для чтения и хотите изменить ее значение, перезапись DLL не работает, вам придется снова скомпилировать все приложения, которые ее используют.
Наконец, я надеюсь, что в этой статье я разъяснил наиболее важные различия между переменными только для чтения и константами.
Таким образом мы можем избежать возможных проблем и еще нескольких компиляций, на которые, я думаю, мы уже тратим много времени. 🤗