- Справочник по C#. Операторы присваивания
- Назначение ссылки
- Составное присваивание
- Присваивание объединения со значением NULL
- Возможность перегрузки оператора
- Спецификация языка C#
- См. также
- Операторы равенства — проверьте, равны ли два объекта
- Оператор равенства ==
- Равенство типов значений
- Равенство ссылочных типов
- Равенство типов записей
- Равенство строк
- Равенство делегатов
- Оператор неравенства !=
- Возможность перегрузки оператора
- Спецификация языка C#
- См. также
- Си шарп переменная равна
- Константы
Справочник по C#. Операторы присваивания
Оператор = присваивания присваивает значение правого операнда переменной, свойству или элементу индексатора , заданному левым операндом. Результатом выражения присваивания является значение, назначенное расположенному слева операнду. Расположенный справа операнд должен иметь тот же тип, что и операнд слева, либо же допускать неявное преобразование в этот тип.
Оператор присваивания = имеет правую ассоциативность, то есть выражение формы:
В следующем примере показано использование оператора присваивания с локальной переменной, свойством и элементом индексатора в качестве левого операнда:
var numbers = new List() < 1.0, 2.0, 3.0 >; Console.WriteLine(numbers.Capacity); numbers.Capacity = 100; Console.WriteLine(numbers.Capacity); // Output: // 4 // 100 int newFirstElement; double originalFirstElement = numbers[0]; newFirstElement = 5; numbers[0] = newFirstElement; Console.WriteLine(originalFirstElement); Console.WriteLine(numbers[0]); // Output: // 1 // 5
Левый операнд назначения получает значение правого операнда. Если операнды относятся к типам значений, присваивание копирует содержимое правого операнда. Если операнды относятся к ссылочным типам, присваивание копирует ссылку в объект .
Это называется назначением значений: присваивается значение .
Назначение ссылки
Назначение = ref ссылки делает его левый операнд псевдонимом правого операнда, как показано в следующем примере:
void Display(double[] s) => Console.WriteLine(string.Join(" ", s)); double[] arr = < 0.0, 0.0, 0.0 >; Display(arr); ref double arrayElement = ref arr[0]; arrayElement = 3.0; Display(arr); arrayElement = ref arr[arr.Length - 1]; arrayElement = 5.0; Display(arr); // Output: // 0 0 0 // 3 0 0 // 3 0 5
В предыдущем примере локальная ссылочная переменная arrayElement инициализируется как псевдоним первого элемента массива. Затем он переназначается ref для ссылки на последний элемент массива. Так как это псевдоним, при обновлении его значения с помощью обычного оператора = присваивания также обновляется соответствующий элемент массива.
Левый операнд присваивания ref может быть локальной ссылочной переменной, полем ref и параметром ref метода , out или in . Оба операнда должны иметь один и тот же тип.
Составное присваивание
Для бинарного оператора op выражение составного присваивания в форме
за исключением того, что x вычисляется только один раз.
Присваивание объединения со значением NULL
Оператор ??= присваивания с объединением значений NULL можно использовать для назначения значения правого операнда левому операнду только в том случае, если левый операнд имеет значение null . Дополнительные сведения см. в статье Операторы ?? и ??=.
Возможность перегрузки оператора
Определяемый пользователем тип не может перегружать оператор присваивания. Однако пользовательский тип может определять неявное преобразование в другой тип. Таким образом, значение пользовательского типа может быть присвоено переменной, свойству или элементу индексатора другого типа. Дополнительные сведения см. в разделе Операторы пользовательского преобразования.
Явная перегрузка составного оператора присваивания для пользовательского типа невозможна. Но если пользовательский тип перегружает бинарный оператор op , существующий оператор op= также будет неявно перегружен.
Спецификация языка C#
Подробные сведения см. в разделе Assignment operators (Операторы присваивания) в спецификации языка C#.
См. также
Операторы равенства — проверьте, равны ли два объекта
Операторы == (равенство) и != (неравенство) проверяют равенство или неравенство своих операндов. Типы значений равны, если их содержимое равно. Ссылочные типы равны, если две переменные ссылаются на одно хранилище.
Оператор равенства ==
Оператор равенства == возвращает значение true , если его операнды равны. В противном случае возвращается значение false .
Равенство типов значений
Операнды встроенных типов значений равны, если равны их значения.
int a = 1 + 2 + 3; int b = 6; Console.WriteLine(a == b); // output: True char c1 = 'a'; char c2 = 'A'; Console.WriteLine(c1 == c2); // output: False Console.WriteLine(c1 == char.ToLower(c2)); // output: True
У операторов == , < , >, = , если какой-то из операндов не является числом (Double.NaN или Single.NaN), результатом операции является false . Это означает, что значение NaN не больше, не меньше и не равно любому другому значению double (или float ), включая NaN . Дополнительные сведения и примеры см. в справочных статьях по Double.NaN или Single.NaN.
Два операнда одного типа enum равны, если равны соответствующие значения базового целочисленного типа.
По умолчанию пользовательские типы struct не поддерживают оператор == . Чтобы поддерживать оператор == , пользовательская структура должна перегружать его.
Операторы и != поддерживаются кортежами == C#. Дополнительные сведения см. в разделе Равенство кортежей статьи Типы кортежей.
Равенство ссылочных типов
По умолчанию два операнда ссылочного типа, отличные от записи, являются равными, если они ссылаются на один и тот же объект.
public class ReferenceTypesEquality < public class MyClass < private int id; public MyClass(int id) =>this.id = id; > public static void Main() < var a = new MyClass(1); var b = new MyClass(1); var c = a; Console.WriteLine(a == b); // output: False Console.WriteLine(a == c); // output: True >>
Как показано в примере, определяемые пользователем ссылочные типы поддерживают оператор == по умолчанию. Однако ссылочный тип может перегружать оператор == . Если ссылочный тип перегружает оператор == , воспользуйтесь методом Object.ReferenceEquals, чтобы проверить, что две ссылки этого типа указывают на один и тот же объект.
Равенство типов записей
Типы записей, доступные в C# 9.0 и более поздних версий, поддерживают операторы == и != , которые по умолчанию обеспечивают семантику равенства значений. То есть два операнда записи равны, когда оба они равны null или равны соответствующие значения всех полей и автоматически реализуемых свойств.
public class RecordTypesEquality < public record Point(int X, int Y, string Name); public record TaggedNumber(int Number, ListTags); public static void Main() < var p1 = new Point(2, 3, "A"); var p2 = new Point(1, 3, "B"); var p3 = new Point(2, 3, "A"); Console.WriteLine(p1 == p2); // output: False Console.WriteLine(p1 == p3); // output: True var n1 = new TaggedNumber(2, new List() < "A" >); var n2 = new TaggedNumber(2, new List() < "A" >); Console.WriteLine(n1 == n2); // output: False > >
Как показано в предыдущем примере, для элементов ссылочного типа, не относящихся к записям, сравниваются их ссылочные значения, а не упоминаемые экземпляры.
Равенство строк
Два операнда string равны, если они оба имеют значение null или оба экземпляра строки имеют одинаковую длину и идентичные символы в каждой позиции символа.
string s1 = "hello!"; string s2 = "HeLLo!"; Console.WriteLine(s1 == s2.ToLower()); // output: True string s3 = "Hello!"; Console.WriteLine(s1 == s3); // output: False
Сравнения на равенство строк — это порядковые сравнения с учетом регистра. Дополнительные сведения о том, как сравнивать строки, см. в статье Сравнение строк в C#.
Равенство делегатов
Два операнда делегатов одного типа среды выполнения равны, если оба из них имеют значение null или их списки вызовов имеют одинаковую длину и содержат одинаковые записи в каждой позиции:
Action a = () => Console.WriteLine("a"); Action b = a + a; Action c = a + a; Console.WriteLine(object.ReferenceEquals(b, c)); // output: False Console.WriteLine(b == c); // output: True
Подробные сведения см. в разделе Delegate equality operators (Операторы равенства делегатов) в спецификации языка C#.
Делегаты, созданные в результате вычисления семантически идентичных лямбда-выражений , не равны, как показано в следующем примере:
Action a = () => Console.WriteLine("a"); Action b = () => Console.WriteLine("a"); Console.WriteLine(a == b); // output: False Console.WriteLine(a + b == a + b); // output: True Console.WriteLine(b + a == a + b); // output: False
Оператор неравенства !=
Оператор != неравенства возвращает значение true , если его операнды не равны, false в противном случае . Для операндов встроенных типов выражение x != y дает тот же результат, что и выражение !(x == y) . Дополнительные сведения о равенстве типов см. в разделе Оператор равенства.
В следующем примере иллюстрируется использование оператора != .
int a = 1 + 1 + 2 + 3; int b = 6; Console.WriteLine(a != b); // output: True string s1 = "Hello"; string s2 = "Hello"; Console.WriteLine(s1 != s2); // output: False object o1 = 1; object o2 = 1; Console.WriteLine(o1 != o2); // output: True
Возможность перегрузки оператора
Определяемый пользователем тип может перегружать операторы == и != . Если тип перегружает один из двух операторов, он должен также перегружать и другой.
Тип записи не может явно перегружать операторы == и != . Если необходимо изменить поведение операторов == и != для типа записи T , реализуйте метод IEquatable.Equals со следующей сигнатурой.
public virtual bool Equals(T? other);
Спецификация языка C#
Дополнительные сведения о равенстве типов записей см. в разделе Элементы равенствапредложения функции записей.
См. также
Си шарп переменная равна
Для хранения данных в программе применяются переменные . Переменная представляет именнованную область памяти, в которой хранится значение определенного типа. Переменная имеет тип, имя и значение. Тип определяет, какого рода информацию может хранить переменная.
Перед использованием любую переменную надо определить. Синтаксис определения переменной выглядит следующим образом:
Вначале идет тип переменной, потом ее имя. В качестве имени переменной может выступать любое произвольное название, которое удовлетворяет следующим требованиям:
- имя может содержать любые цифры, буквы и символ подчеркивания, при этом первый символ в имени должен быть буквой или символом подчеркивания
- в имени не должно быть знаков пунктуации и пробелов
- имя не может быть ключевым словом языка C#. Таких слов не так много, и при работе в Visual Studio среда разработки подсвечивает ключевые слова синим цветом.
Хотя имя переменой может быть любым, но следует давать переменным описательные имена, которые будут говорить об их предназначении.
Например, определим простейшую переменную:
В данном случае определена переменная name, которая имеет тип string . то есть переменная представляет строку. Поскольку определение переменной представляет собой инструкцию, то после него ставится точка с запятой.
При этом следует учитывать, что C# является регистрозависимым языком, поэтому следующие два определения переменных будут представлять две разные переменные:
После определения переменной можно присвоить некоторое значение:
Так как переменная name представляет тип string, то есть строку, то мы можем присвоить ей строку в двойных кавычках. Причем переменной можно присвоить только то значение, которое соответствует ее типу.
В дальнейшем с помощью имени переменной мы сможем обращаться к той области памяти, в которой хранится ее значение.
Также мы можем сразу при определении присвоить переменной значение. Данный прием называется инициализацией:
Отличительной чертой переменных является то, что в программе можно многократно менять их значение. Например, создадим небольшую программу, в которой определим переменную, поменяем ее значение и выведем его на консоль:
string name = "Tom"; // определяем переменную и инициализируем ее Console.WriteLine(name); // Tom name = "Bob"; // меняем значение переменной Console.WriteLine(name); // Bob
Консольный вывод программы:
Константы
Отличительной особенностью переменных является то, что мы можем изменить их значение в процессе работы программы. Но, кроме того, в C# есть константы. Константа должна быть обязательно инициализирована при определении, и после определения значение константы не может быть изменено
Константы предназначены для описания таких значений, которые не должны изменяться в программе. Для определения констант используется ключевое слово const , которое указывается перед типом константы:
const string NAME = "Tom"; // определяем константу
Так, в данном случае определена константа NAME , которая хранит строку «Tom». Нередко для название констант используется верхний регистр, но это не более чем условность.
При использовании констант надо помнить, что объявить мы их можем только один раз и что к моменту компиляции они должны быть определены. Так, в следующем случае мы получим ошибку, так как константе не присвоено начальное значение:
const string NAME; // ! Ошибка - константа NAME не инициализирована
Кроме того, мы ее не сможем изменить в процессе работы программы:
const string NAME = "Tom"; // определяем константу NAME = "Bob"; // !Ошибка - у констаты нельзя изменить значение
Таким образом, если нам надо хранить в программе некоторые данные, но их не следует изменить, они определяются в виде констант. Если же их можно изменять, то они определяются в виде переменных.