简体   繁体   English

SequenceEqual不调用父类型中的Equals

[英]SequenceEqual not calling Equals in parent type

A parent type: 父类型:

public class IdObject : IComparable<IdObject>, IEquatable<IdObject>
{
    public int id { get; set; }

    public bool Equals(IdObject other)
    {
        if (other == null) return this == null;
        if (this == null) return false;
        var test = other.id.CompareTo(this.id);

        return other.id.CompareTo(this.id) == 0;
    }

    public int CompareTo(IdObject other)
    {
        return other.id.CompareTo(this.id);
    }
}

A child: 一个孩子:

public class NamedObject : IdObject
{
    public string name { get; set; }
}

Comparing lists of IdObject s 比较IdObject的列表

var list1 = new List<IdObject>()
{
    new IdObject() { id = 42 },
    new IdObject() { id = 43 }
};
var list2 = new List<IdObject>()
{
    new IdObject() { id = 43 },
    new IdObject() { id = 42 }
};
list1.Sort();
list2.Sort();
var test = list1.SequenceEqual(list2); // True

Comparing lists of Named s 比较Named的列表

var list1 = new List<NamedObject>()
{
    new NamedObject() { id = 42 },
    new NamedObject() { id = 43 }
};
var list2 = new List<NamedObject>()
{
    new NamedObject() { id = 43 },
    new NamedObject() { id = 42 }
};
list1.Sort();
list2.Sort();
var test = list1.SequenceEqual(list2); // False

I realized that IdObject::Equals is not called through a NamedObject context. 我意识到没有通过NamedObject上下文调用IdObject::Equals

Am I doing something wrong ? 难道我做错了什么 ?
Isn't supposed to call the inherited Equals ? 不应称呼继承的Equals吗?
How can I use the parent's Equals ? 如何使用父母的Equals

Basically, you've got a problem because your type doesn't override object.Equals(object) in a way consistent with your IEquatable<T> implementation and you're dealing with a collection of the subclasses. 基本上,您会遇到问题,因为您的类型不会object.Equals(object)IEquatable<T>实现一致的方式覆盖object.Equals(object)并且您正在处理子类的集合。

SequenceEqual will be using EqualityComparer<NamedObject>.Default . SequenceEqual将使用EqualityComparer<NamedObject>.Default That will check whether NamedObject implements IEquatable<NamedObject> - and will find that it doesn't, so it will fall back to calling object.Equals(object) . 这将检查NamedObject是否实现IEquatable<NamedObject> -并发现它没有实现,因此将退回到调用object.Equals(object) You can see this here: 您可以在这里看到:

using System;
using System.Collections.Generic;

public class Base : IEquatable<Base>
{
    public override bool Equals(object other)
    {
        Console.WriteLine("Equals(object)");
        return false;
    }

    public bool Equals(Base other)
    {
        Console.WriteLine("Equals(Base)");
        return false;
    }

    public override int GetHashCode() => 0;
}

public class Derived : Base
{
}

public class Test
{
    static void Main()
    {
        var comparer = EqualityComparer<Derived>.Default;        
        Console.WriteLine(comparer.Equals(new Derived(), new Derived()));
    }
}

You don't override object.Equals(object) , so you've effectively got reference equality. 您不会覆盖object.Equals(object) ,因此您实际上已经获得了引用相等性。

I would recommend that you override object.Equals(object) and object.GetHashCode() in your base class. 我建议您在基类中重写object.GetHashCode() object.Equals(object)object.GetHashCode()

You could then also implement IEquatable<NamedObject> in NamedObject , just delegating to the base implementation or (better) checking the name as well, unless you really don't want that to be taken into account. 然后,您还可以NamedObject实现IEquatable<NamedObject> ,仅委托给基本实现或(更好地)检查名称,除非您确实不希望将其考虑在内。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM