Поделиться через


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

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

Оператор сопоставления шаблонов можно использовать is в качестве альтернативы == тесту при тестировании с константным значением. Оператор is использует семантику равенства по умолчанию для всех типов значений и ссылок.

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

Оператор равенства == возвращает значение 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

Это важно

Равные записи в списке вызовов включают все фиксированные параметры в вызове, включая приемника. Получатель — это экземпляр объекта, this представленного при вызове записи.

var o1 = new object();
var o2 = new object();
var d1 = o1.ToString;
var d2 = o2.ToString;
Console.WriteLine(object.ReferenceEquals(d1, d2));  // output: False
Console.WriteLine(d1 == d2);  // output: False (different receivers)

Подробные сведения см. в разделе 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#.

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

См. также