Кто не сомневается, когда начинает узнавать что-то новое? 🤔

Весь мир

В этом случае, когда кто-то начинает программировать в .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 не работает, вам придется снова скомпилировать все приложения, которые ее используют.

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

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