Следующее вызовет бесконечную рекурсию в методе перегрузки оператора ==.
Foo foo1 = null;
Foo foo2 = new Foo();
Assert.IsFalse(foo1 == foo2);
public static bool operator ==(Foo foo1, Foo foo2) {
if (foo1 == null) return foo2 == null;
return foo1.Equals(foo2);
}
Как проверить наличие нулей?
c#
.net
operator-overloading
Эндрю Джонс
источник
источник
Assert.IsFalse(foo2 == foo1);
foo1.Equals(foo2)
значит, если, например, я хочуfoo1 == foo2
только еслиfoo1.x == foo2.x && foo1.y == foo2.y
? Разве это не ответ, игнорируя случай, где,foo1 != null
ноfoo2 == null
?if (foo1 is null) return foo2 is null;
Привести к объекту в методе перегрузки:
источник
(object)foo1 == null
илиfoo1 == (object)null
перейдут к встроенной перегрузке,==(object, object)
а не к пользовательской перегрузке==(Foo, Foo)
. Это похоже на разрешение перегрузки методов.Используйте
ReferenceEquals
. На форумах MSDN :источник
Пытаться
Object.ReferenceEquals(foo1, null)
В любом случае я бы не рекомендовал перегружать
==
оператора; его следует использовать для сравнения ссылок и использоватьEquals
для «семантических» сравнений.источник
Если я переопределил
bool Equals(object obj)
и хочу, чтобы оператор==
иFoo.Equals(object obj)
возвращал одно и то же значение, я обычно реализую!=
оператор следующим образом:Затем оператор
==
после выполнения всех проверок на null для меня в конечном итоге вызовет то,foo1.Equals(foo2)
что я переопределил, чтобы выполнить фактическую проверку, равны ли они.источник
Object.Equals(Object, Object)
бок о бокObject.ReferenceEquals(Object, Object)
, довольно ясно, что онObject.Equals(Object, Object)
делает все, как предлагается в других ответах из коробки. Почему бы не использовать это?==
оператор, если все, что вам нужно, - это поведение по умолчанию. Вы должны выполнять перегрузку только тогда, когда вам нужно реализовать собственную логику сравнения, т. Е. Нечто большее, чем проверка эталонного равенства.==
желательна (вопрос подразумевает это), я просто поддерживаю этот ответ, предполагая, чтоObject.Equals(Object, Object)
другие уловки, такие как использованиеReferenceEquals
или явное приведение типов, становятся ненужными (таким образом, «почему бы не использовать это?», «это» бытьEquals(Object, Object)
). Даже если вы не связаны, ваша точка зрения также верна, и я бы пошел дальше: только перегрузку==
для объектов, которые мы можем классифицировать как «объекты-значения».Object.Equals(Object, Object)
в свою очередь вызывает Object.Equals (Object), который является виртуальным методом, который, вероятно, переопределяет Foo. Тот факт, что вы ввели виртуальный вызов в свою проверку на равенство, может повлиять на способность компилятора оптимизировать (например, встраивать) эти вызовы. Это, вероятно, незначительно для большинства целей, но в некоторых случаях небольшие затраты на оператор равенства могут означать огромные затраты на циклы или сортированные структуры данных.Если вы используете C # 7 или новее, вы можете использовать сопоставление с нулевым постоянным шаблоном:
Это дает вам немного более аккуратный код, чем один вызывающий объект .ReferenceEquals (foo1, null)
источник
public static bool operator==( Foo foo1, Foo foo2 ) => foo1?.Equals( foo2 ) ?? foo2 is null;
В этом случае есть более простой способ проверки
null
:Это оно!
Эта функция была представлена в C # 7
источник
Мой подход - делать
на что я полагаюсь на
object
собственный оператор равенства, который не может ошибиться. Или собственный метод расширения (и перегрузка):или для обработки большего количества дел может быть:
Ограничение предотвращает использование
IsNull
типов значений. Теперь это так же мило, как звонитьЭто означает, что у меня есть один последовательный / не подверженный ошибкам стиль проверки на нули повсюду. Я также обнаружил, что
(object)item == null
это очень-очень-очень немного быстрееObject.ReferenceEquals(item, null)
, но только если это имеет значение (в настоящее время я работаю над чем-то, где я должен все микро-оптимизировать!).Чтобы увидеть полное руководство по внедрению проверок равенства, см. Что такое «лучшая практика» для сравнения двух экземпляров ссылочного типа?
источник
DbNull
, ИМО, случаи, когда это не приведет к возникновению проблем, связанных с SRP , довольно редки. Просто указав на запах кода, это вполне могло быть уместным.Статический
Equals(Object, Object)
метод указывает, равны ли два объекта,objA
иobjB
. Это также позволяет вам тестировать объекты, значение которых соответствуетnull
равенству. Он сравниваетobjA
иobjB
на равенство следующим образом:true
. Этот тест эквивалентен вызовуReferenceEquals
метода. Кроме того, если обаobjA
иobjB
естьnull
, метод возвращаетtrue
.objA
илиobjB
естьnull
. Если так, он возвращаетсяfalse
. Если два объекта не представляют одну и ту же ссылку на объект, и ни один из них не являетсяnull
, он вызываетobjA.Equals(objB)
и возвращает результат. Это означает, что приobjA
переопределенииObject.Equals(Object)
метода вызывается это переопределение..
источник
больше отвечая на переопределяющий оператор, как сравнить с null, который перенаправляется здесь как дубликат.
В тех случаях, когда это делается для поддержки объектов-значений, я считаю новую нотацию удобной и хочу убедиться, что есть только одно место, где производится сравнение. Также использование Object.Equals (A, B) упрощает нулевые проверки.
Это приведет к перегрузке ==,! =, Equals и GetHashCode
Для более сложных объектов добавьте дополнительные сравнения в Equals и более богатый GetHashCode.
источник
Для современного сжатого синтаксиса:
источник
проверь это
справочные руководства по перегрузке Equals () и Operator ==
источник
Вы можете попробовать использовать свойство объекта и поймать результирующее исключение NullReferenceException. Если свойство, которое вы пробуете, унаследовано или переопределено от Object, то это работает для любого класса.
источник