Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net LINQ中的DefaultEquality比较器_.net_Comparison - Fatal编程技术网

.net LINQ中的DefaultEquality比较器

.net LINQ中的DefaultEquality比较器,.net,comparison,.net,Comparison,我有以下代码 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { List<I> bars = new List&l

我有以下代码

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            List<I> bars = new List<I>();
            bars.Add(new A() { Id = 1 });
            bars.Add(new B() { Id = 1 });
            bars.Add(new A() { Id = 1 });

            var distictBars = bars.Distinct();

            foreach (var item in distictBars)
            {
                Debug.WriteLine(item.Name);
            }
        }
    }

    interface I
    {
        string Name { get; }
    }

    class Base
    {
        public int Id { get; set; }
    }

    class A : Base, I, IEquatable<A>
    {
        public string Name
        {
            get { return this.Id + "-A"; }
        }

        public bool Equals(A other)
        {
            return this.Id == other.Id;
        }

        public override bool Equals(object obj)
        {
            if (obj is A)
                return this.Equals(obj as A);
            else
                return object.ReferenceEquals(this, obj);
        }
    }

    class B : Base, I, IEquatable<B>
    {
        public string Name
        {
            get { return this.Id + "-B"; }
        }

        public bool Equals(B other)
        {
            return this.Id == other.Id;
        }

        public override bool Equals(object obj)
        {
            if (obj is A)
                return this.Equals(obj as A);
            else
                return object.ReferenceEquals(this, obj);
        }
    }
}
不过,我需要以下几点

1-A 
1-B 
1-A 
1-A 
1-B
也就是说,消除类型A或B的重复项。
Distinct
LINQ方法似乎没有考虑我的Equals覆盖,也没有考虑IEquitable接口实现


除了该方法进行指定的比较外,我应该如何按顺序进行?

Distinct
方法可能会在内部使用类似于
哈希集的东西,它依赖于哈希代码(显然)。您还需要覆盖
GetHashCode


在我看来,你总的来说有一些不必要的重复。您的
A
B
类在确定相等性方面具有基本相同的逻辑;如果两个
Base
对象的ID相等且类型相同,您希望确保它们相等吗?(在我看来就是这样;在本例中,您的实现似乎包含几个错误,但这仍然是我最好的猜测。)

如果是这样,只需使
Base
实现
IEquatable
,您的
A
B
实现就会变得简单得多:

class Base : IEquatable<Base>
{
    public Base(int id)
    {
        Id = id;
    }

    public int Id { get; private set; }

    public bool Equals(Base other)
    {
        if (other == null)
        {
            return false;
        }

        // Ensure As only compare equal with other As
        // and the same for Bs (and potentially other subtypes).
        return other.GetType().Equals(GetType()) && other.Id == Id;
    }

    public override bool Equals(object other)
    {
        if (other is Base)
        {
            return Equals((Base)other);
        }

        return false;
    }

    public override int GetHashCode()
    {
        return Id;
    }
}

class A : Base, I
{
    public A(int id) : base(id)
    { }

    public string Name
    {
        get { return this.Id + "-A"; }
    }
}

class B : Base, I
{
    public B(int id) : base(id)
    { }

    public string Name
    {
        get { return this.Id + "-B"; }
    }
}

Distinct
方法可能会在内部使用类似于
HashSet
的东西,它依赖于散列码(显然)。您还需要覆盖
GetHashCode


在我看来,你总的来说有一些不必要的重复。您的
A
B
类在确定相等性方面具有基本相同的逻辑;如果两个
Base
对象的ID相等且类型相同,您希望确保它们相等吗?(在我看来就是这样;在本例中,您的实现似乎包含几个错误,但这仍然是我最好的猜测。)

如果是这样,只需使
Base
实现
IEquatable
,您的
A
B
实现就会变得简单得多:

class Base : IEquatable<Base>
{
    public Base(int id)
    {
        Id = id;
    }

    public int Id { get; private set; }

    public bool Equals(Base other)
    {
        if (other == null)
        {
            return false;
        }

        // Ensure As only compare equal with other As
        // and the same for Bs (and potentially other subtypes).
        return other.GetType().Equals(GetType()) && other.Id == Id;
    }

    public override bool Equals(object other)
    {
        if (other is Base)
        {
            return Equals((Base)other);
        }

        return false;
    }

    public override int GetHashCode()
    {
        return Id;
    }
}

class A : Base, I
{
    public A(int id) : base(id)
    { }

    public string Name
    {
        get { return this.Id + "-A"; }
    }
}

class B : Base, I
{
    public B(int id) : base(id)
    { }

    public string Name
    {
        get { return this.Id + "-B"; }
    }
}

您需要覆盖对象中的
.GetHashCode()
。我建议这样做:

public override int GetHashCode() {
    return this.Id;
}

您需要覆盖对象中的
.GetHashCode()
。我建议这样做:

public override int GetHashCode() {
    return this.Id;
}

覆盖GetHashCode。。。我该怎么回那里?身份证?@serhio:当然可以。如果两个对象相等,那么GetHashCode()应该返回相同的值。由于ID是唯一要比较的对象,因此返回此.ID.GetHashCode()。如果要比较更多,则对所有比较字段的GetHashCode()值进行异或运算。@mattmc3:Int32.GetHashCode()只返回整数@塞里奥:我就是这么说的,不是吗?您当前的实现可能会进入一个无限递归循环(这将使堆栈溢出)。所以,我需要实现IEquatable吗?重写GetHashCode。。。我该怎么回那里?身份证?@serhio:当然可以。如果两个对象相等,那么GetHashCode()应该返回相同的值。由于ID是唯一要比较的对象,因此返回此.ID.GetHashCode()。如果要比较更多,则对所有比较字段的GetHashCode()值进行异或运算。@mattmc3:Int32.GetHashCode()只返回整数@塞里奥:我就是这么说的,不是吗?您当前的实现可能会进入无限递归循环(这将使堆栈溢出)。因此,我需要实现IEquatable吗?