Кроме полей класс может определять для хранения данных константы. В отличие от полей их значение устанавливается один раз непосредственно при их объявлении и впоследствии не может быть изменено. Кроме того, константы хранят некоторые данные, которые относятся не к одному объекту, а ко всему классу в целом. И для обращения к константам применяется не имя объекта, а имя класса:
Person tom = new Person(); tom.name = "Tom"; tom.Print(); // Person: Tom Console.WriteLine(Person.type); // Person // Person.type = "User"; // !Ошибка: изменить константу нельзя class Person { public const string type = "Person"; public string name = "Undefined"; public void Print() => Console.WriteLine($"{type}: {name}"); }
Здесь в классе Person определена константа type
, которая хранит название класса:
public const string type = "Person";
Название класса не зависит от объекта. Мы можем создать много объектов Person, но название класса от этого не должно измениться - оно относится ко всем объектам Person и не должно меняться. Поэтому название типа можно сохранить в виде константы.
Стоит отметить, что константе сразу при ее определении необходимо присвоить значение.
Подобно обычным полям мы можем обращаться к константам класса внутри этого класса. Например, в методе Print значение константы выводится на консоль.
Однако если мы хотим обратиться к константе вне ее класса, то для обращения необходимо использовались имя класса:
Console.WriteLine(Person.type); // Person
Таким образом, если необходимо хранить данные, которые относятся ко всему классу в целом, то можно использовать константы.
Поля для чтения представляют такие поля класса или структуры, значение которых нельзя изменить. Таким полям можно присвоить значение либо при непосредственно при их объявлении, либо в конструкторе. В других местах программы присваивать значение таким полям нельзя, можно только считывать их значение.
Поле для чтения объявляется с ключевым словом readonly:
Person tom = new Person("Tom"); Console.WriteLine(tom.name); //tom.name = "Sam"; // !Ошибка: нельзя изменить class Person { public readonly string name = "Undefined"; // можно так инициализировать public Person(string name) { this.name = name; // в конструкторе также можно присвоить значение полю для чтения } public void ChangeName(string otherName) { //this.name = otherName; // так нельзя } }
Здесь поле name
хранит имя пользователя и представляет поле для чтения. Ему можно присвоить значение непосредственно при объявлении:
public readonly string name = "Undefined";
Либо можно присвоить значение в конструкторе
public Person(string name) { this.name = name; }
В остальных местах программы, в том числе в самом классе Person присвоить значение полю для чтения нельзя.
Константы должны быть определены во время компиляции, а поля для чтения могут быть определены во время выполнения программы.
Соответственно значение константы можно установить только при ее определении.
Поле для чтения можно инициализировать либо при его определении, либо в конструкторе класса.
Константы не могут использовать модификатор static, так как уже неявно являются статическими. Поля для чтения могут быть как статическими, так и не статическими.
Кроме полей для чтения в C# можно определять структуры для чтения. Для этого они предваряются модификатором readonly:
readonly struct Person { }
Особенностью таких структур является то, что все их поля должны быть также полями для чтения:
readonly struct Person { public readonly string name; public Person(string name) { this.name = name; } }
То же самое касается и свойств, которые должны быть доступны только для чтения:
readonly struct Person { public readonly string Name { get; } // указывать readonly необязательно public int Age { get; } // свойство только для чтения public Person(string name, int age) { Name = name; Age = age; } }