如何检查 '==' 中的空值 没有无限递归的运算符重载?

发布于 2024-07-04 03:05:09 字数 295 浏览 10 评论 0原文

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

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

如何检查空值?

The following will cause infinite recursion on the == operator overload method

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

How do I check for nulls?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

多彩岁月 2024-07-11 03:05:09

您可以尝试使用对象属性并捕获生成的 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;
}

You can try to use an object property and catch the resulting NullReferenceException. If the property you try is inherited or overridden from Object, then this works for any class.

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;
}
剪不断理还乱 2024-07-11 03:05:09

回复更多重写运算符如何与 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 中添加额外的比较。

replying more to overriding operator how to compare to null that redirects here as a duplicate.

In the cases where this is being done to support Value Objects, I find the new notation to handy, and like to ensure there is only one place where the comparison is made. Also leveraging Object.Equals(A, B) simplifies the null checks.

This will overload ==, !=, Equals, and 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();

For more complicated objects add additional comparisons in Equals and a richer GetHashCode.

叶落知秋 2024-07-11 03:05:09

重载运算符 == 时的一个常见错误是使用 (a == b)(a ==null)(b = = null) 检查引用是否相等。 这个代替
导致调用重载运算符 ==,从而导致无限循环。 使用 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() 的指南和运算符 ==

A common error in overloads of operator == is to use (a == b), (a ==null), or (b == null) to check for reference equality. This instead
results in a call to the overloaded operator ==, causing an infinite loop. Use ReferenceEquals or cast the type to Object, to avoid the
loop.

check out this

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

reference Guidelines for Overloading Equals() and Operator ==

心是晴朗的。 2024-07-11 03:05:09

尝试 Object.ReferenceEquals(foo1, null)

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

Try Object.ReferenceEquals(foo1, null)

Anyway, I wouldn't recommend overloading the ==operator; it should be used for comparing references, and use Equals for "semantic" comparisons.

影子是时光的心 2024-07-11 03:05:09

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

if (foo is null)

就是这样!

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

There is actually a simpler way of checking against null in this case:

if (foo is null)

That's it!

This feature was introduced in C# 7

辞旧 2024-07-11 03:05:09

如果我重写了 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) 我已经重写它来进行实际检查两者是否相等。

If I have overridden bool Equals(object obj) and I want the operator == and Foo.Equals(object obj) to return the same value, I usually implement the != operator like this:

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

The operator == will then after doing all the null checks for me end up calling foo1.Equals(foo2) that I have overridden to do the actual check if the two are equal.

聆听风音 2024-07-11 03:05:09

我的方法是依靠 object 自己的相等运算符来完成

(object)item == null

,这不会出错。 或者自定义扩展方法(和重载):

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 == nullObject 快得多。 ReferenceEquals(item, null),但前提是它很重要(我目前正在研究一些必须对所有内容进行微优化的事情!)。

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

My approach is to do

(object)item == null

upon which I'm relying on object's own equality operator which can't go wrong. Or a custom extension method (and an overload):

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

or to handle more cases, may be:

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

The constraint prevents IsNull on value types. Now its as sweet as calling

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

which means I have one consistent/not-error-prone style of checking for nulls throughout. I also have found (object)item == null is very very very slightly faster than Object.ReferenceEquals(item, null), but only if it matters (I'm currently working on something where I've to micro-optimize everything!).

To see a complete guide on implementing equality checks, see What is "Best Practice" For Comparing Two Instances of a Reference Type?

揪着可爱 2024-07-11 03:05:09

对于现代和简洁的语法:

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

For a modern and condensed syntax:

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);
}
七度光 2024-07-11 03:05:09

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

  • 它确定两个对象是否表示相同的对象引用。 如果这样做,该方法将返回true。 此测试相当于调用 ReferenceEquals 方法。 此外,如果 objAobjB 均为 null,则该方法返回 true
  • 它确定 objAobjB 是否为 null。 如果是,则返回false
    如果两个对象不代表相同的对象引用,且都不为 null,则调用 objA.Equals(objB) 并返回结果。 这意味着如果 objA 重写 Object.Equals(Object) 方法,则会调用此重写。

public static bool operator ==(Foo objA, Foo objB) {
    return Object.Equals(objA, objB);
}

The static Equals(Object, Object) method indicates whether two objects, objA and objB, are equal. It also enables you to test objects whose value is null for equality. It compares objA and objB for equality as follows:

  • It determines whether the two objects represent the same object reference. If they do, the method returns true. This test is equivalent to calling the ReferenceEquals method. In addition, if both objA and objB are null, the method returns true.
  • It determines whether either objA or objB is null. If so, it returns false.
    If the two objects do not represent the same object reference and neither is null, it calls objA.Equals(objB) and returns the result. This means that if objA overrides the Object.Equals(Object) method, this override is called.

.

public static bool operator ==(Foo objA, Foo objB) {
    return Object.Equals(objA, objB);
}
忆依然 2024-07-11 03:05:09

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

Use 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);
}
你与清晨阳光 2024-07-11 03:05:09

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

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

Cast to object in the overload method:

public static bool operator ==(Foo foo1, Foo foo2) {
    if ((object) foo1 == null) return (object) foo2 == null;
    return foo1.Equals(foo2);
}
柏拉图鍀咏恒 2024-07-11 03:05:09

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

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

这为您提供了比调用 object.ReferenceEquals(foo1, null) 的代码稍微简洁的代码

If you are using C# 7 or later you can use null constant pattern matching:

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

This gives you slightly neater code than the one calling object.ReferenceEquals(foo1, null)

旧情别恋 2024-07-11 03:05:09

使用 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;
}

Use ReferenceEquals. From the MSDN forums:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文