Операторы равенства — проверка того, равны ли два объекта или нет

Операторы == (равенство) и != (неравенство) проверяют равенство или неравенство своих операндов. Типы значений равны, если их содержимое равно. Ссылочные типы равны, если две переменные ссылаются на одно хранилище.

Оператор равенства ==

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

Равенство типов записей

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

public class RecordTypesEquality
{
    public record Point(int X, int Y, string Name);
    public record TaggedNumber(int Number, List<string> Tags);

    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<string>() { "A" });
        var n2 = new TaggedNumber(2, new List<string>() { "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<T>.Equals со следующей сигнатурой.

public virtual bool Equals(T? other);

Спецификация языка C#

Дополнительные сведения см. в разделе Операторы отношения и проверки типа в статье по спецификации языка C#.

Дополнительные сведения о равенстве типов записей см. в разделе Элементы равенствапредложения функции записей.

См. также