Вы можете сравнить строку и константу , используя шаблон is
, который является новым в C # 7.
Наиболее распространенное использование этого шаблонабудет делать нулевые проверки, не вызывая оператор равенства.
Возьмите этот пример:
using System;
public class Program
{
public static void Main()
{
var test = new Test();
Console.WriteLine(test == null);
Console.WriteLine(test is null);
}
public class Test
{
public static bool operator ==(Test a, Test b)
{
Console.WriteLine("==");
return ReferenceEquals(a, b);
}
public static bool operator !=(Test a, Test b)
{
Console.WriteLine("!=");
return !ReferenceEquals(a, b);
}
}
}
Это выведет:
==
False
False
, означающее, что *Оператор 1016 *, сравнивающий Test
и константу, будет вызван только один раз.При использовании is
не будет.Это удобно для проверки по null
без использования ReferenceEquals
(хотя ReferenceEquals
фактически специально обрабатывается компилятором).(см. далее ниже для получения дополнительной информации).
Однако для строк это дает очень мало преимуществ, так как компилятор уже делает много магического переписывания для вас.
Если вы используете строку вместотипа из моего примера выше, инструкция ceq
, которая является прямым сравнением, будет выполнена в обоих случаях, даже если строка перегружена оператором ==
.
Редактировать: Как было отмечено @ meJustAndrew в комментариях, это потому, что сравнение выполняется по ссылке, как если бы она была типа object
, и, следовательно, операторы не задействованы.Из его ответа вы можете увидеть здесь, внизу, что на самом деле происходит.Сгенерированный код test is null
идентичен коду из (object)test == null
.
Однако это конкретное преобразование выполняется только для ссылочных типов.
Если код в Main
выше было
var test = (int?)10;
Console.WriteLine(test == null);
Console.WriteLine(test is null);
оба скомпилировали бы в этот эквивалентный код:
Console.WriteLine(test.HasValue == false);
Однако, это просто еще одна область, где задействовано много магии компилятора.