121

以下将导致 == 运算符重载方法的无限递归

    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);
    }

如何检查空值?

4

13 回答 13

146

使用ReferenceEquals

Foo foo1 = null;
Foo foo2 = new Foo();
Assert.IsFalse(foo1 == foo2);

public static bool operator ==(Foo foo1, Foo foo2) {
    if (object.ReferenceEquals(null, foo1))
        return object.ReferenceEquals(null, foo2);
    return foo1.Equals(foo2);
}
于 2008-09-16T15:41:17.013 回答
20

在重载方法中强制转换为对象:

public static bool operator ==(Foo foo1, Foo foo2) {
    if ((object) foo1 == null) return (object) foo2 == null;
    return foo1.Equals(foo2);
}
于 2008-09-16T15:40:56.467 回答
8

使用ReferenceEquals. 从MSDN 论坛

public static bool operator ==(Foo foo1, Foo foo2) {
    if (ReferenceEquals(foo1, null)) return ReferenceEquals(foo2, null);
    if (ReferenceEquals(foo2, null)) return false;
    return foo1.field1 == foo2.field2;
}
于 2008-09-16T15:51:27.347 回答
8

如果您使用的是 C# 7 或更高版本,则可以使用空常量模式匹配:

public static bool operator==(Foo foo1, Foo foo2)
{
    if (foo1 is null)
        return foo2 is null;
    return foo1.Equals(foo2);
}

这给你的代码比调用 object.ReferenceEquals(foo1, null)

于 2017-06-05T20:08:01.673 回答
4

尝试Object.ReferenceEquals(foo1, null)

无论如何,我不建议重载==运算符;它应该用于比较引用,并Equals用于“语义”比较。

于 2008-09-16T15:42:46.760 回答
4

如果我已经重写bool Equals(object obj)并且我想要运算符==Foo.Equals(object obj)返回相同的值,我通常会!=像这样实现运算符:

public static bool operator ==(Foo foo1, Foo foo2) {
  return object.Equals(foo1, foo2);
}
public static bool operator !=(Foo foo1, Foo foo2) {
  return !object.Equals(foo1, foo2);
}

然后,操作员==将在为我完成所有空值检查后最终调用foo1.Equals(foo2)我已覆盖的实际检查两者是否相等。

于 2008-09-17T10:18:27.560 回答
4

null在这种情况下,实际上有一种更简单的检查方法:

if (foo is null)

就是这样!

此功能是在 C# 7 中引入的

于 2019-02-07T15:19:58.433 回答
1

我的方法是做

(object)item == null

我依赖于object自己的不会出错的等式运算符。或自定义扩展方法(和重载):

public static bool IsNull<T>(this T obj) where T : class
{
    return (object)obj == null;
}

public static bool IsNull<T>(this T? obj) where T : struct
{
    return !obj.HasValue;
}

或处理更多案件,可能是:

public static bool IsNull<T>(this T obj) where T : class
{
    return (object)obj == null || obj == DBNull.Value;
}

约束阻止IsNull了值类型。现在它像打电话一样甜蜜

object obj = new object();
Guid? guid = null; 
bool b = obj.IsNull(); // false
b = guid.IsNull(); // true
2.IsNull(); // error

这意味着我有一种始终如一的/不易出错的检查空值的方式。我还发现(object)item == null它比 非常非常非常快Object.ReferenceEquals(item, null),但前提是它很重要(我目前正在做一些我必须对所有内容进行微优化的事情!)。

要查看有关实施相等检查的完整指南,请参阅比较引用类型的两个实例的“最佳实践”是什么?

于 2012-12-16T08:13:26.553 回答
0

静态Equals(Object, Object)方法指示两个对象objAobjB是否相等。它还使您能够测试其值为null相等的对象。它比较objAobjB的相等性如下:

  • 它确定两个对象是否代表相同的对象引用。如果他们这样做,则该方法返回true. 这个测试相当于调用ReferenceEquals方法。此外,如果两者都是objA,则该方法返回。objBnulltrue
  • 它确定是objA还是。如果是,则返回. 如果这两个对象不代表相同的对象引用并且两者都不代表,则调用并返回结果。这意味着如果覆盖该方法,则调用此覆盖。objBnullfalsenullobjA.Equals(objB)objAObject.Equals(Object)

.

public static bool operator ==(Foo objA, Foo objB) {
    return Object.Equals(objA, objB);
}
于 2017-08-02T16:14:56.563 回答
0

更多地回复覆盖操作员如何与在此处重定向为重复的 null 进行比较。

在这样做以支持值对象的情况下,我发现新的符号很方便,并且希望确保只有一个地方进行比较。还利用 Object.Equals(A, B) 简化了空检查。

这将重载 ==、!=、Equals 和 GetHashCode

    public static bool operator !=(ValueObject self, ValueObject other) => !Equals(self, other);
    public static bool operator ==(ValueObject self, ValueObject other) => Equals(self, other);
    public override bool Equals(object other) => Equals(other as ValueObject );
    public bool Equals(ValueObject other) {
        return !(other is null) && 
               // Value comparisons
               _value == other._value;
    }
    public override int GetHashCode() => _value.GetHashCode();

对于更复杂的对象,在 Equals 和更丰富的 GetHashCode 中添加额外的比较。

于 2018-07-16T05:05:53.963 回答
0

对于现代和简洁的语法:

public static bool operator ==(Foo x, Foo y)
{
    return x is null ? y is null : x.Equals(y);
}

public static bool operator !=(Foo x, Foo y)
{
    return x is null ? !(y is null) : !x.Equals(y);
}
于 2019-10-02T05:09:51.210 回答
-3

运算符 == 重载的一个常见错误是使用(a == b), (a ==null), 或(b == null)检查引用相等性。相反,这会 导致调用重载运算符 ==,从而导致infinite loop. 使用ReferenceEquals或将类型转换为 Object,以避免循环。

看看这个

// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))// using ReferenceEquals
{
    return true;
}

// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))// using casting the type to Object
{
    return false;
}

重载 Equals() 和运算符 == 的参考 指南

于 2016-10-18T13:02:52.800 回答
-5

您可以尝试使用对象属性并捕获生成的 NullReferenceException。如果您尝试的属性是从 Object 继承或覆盖的,那么这适用于任何类。

public static bool operator ==(Foo foo1, Foo foo2)
{
    //  check if the left parameter is null
    bool LeftNull = false;
    try { Type temp = a_left.GetType(); }
    catch { LeftNull = true; }

    //  check if the right parameter is null
    bool RightNull = false;
    try { Type temp = a_right.GetType(); }
    catch { RightNull = true; }

    //  null checking results
    if (LeftNull && RightNull) return true;
    else if (LeftNull || RightNull) return false;
    else return foo1.field1 == foo2.field2;
}
于 2008-09-16T15:58:53.710 回答