簡體   English   中英

實現 IEqualityComparer

[英]Implement IEqualityComparer

我想從列表中獲取不同的對象。 我試圖實現IEqualityComparer但沒有成功。 請查看我的代碼並為我解釋IEqualityComparer

public class Message
{
    public int x { get; set; }
    public string y { get; set; }
    public string z { get; set; }
    public string w { get; set; }
}

public class MessageComparer : IEqualityComparer<Message>
{
    public bool Equals(Message x, Message y)
    {
        if (Object.ReferenceEquals(x, y)) return true;

        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        if (x.x == y.x && x.y == y.y && x.z == y.z && x.w == y.w)
        {
            return true;
        }

        return false;
    }

    public int GetHashCode(Message number)
    {
        // if (Object.ReferenceEquals(number, null)) return 0;
        int hashX = number.x.GetHashCode();
        int hashY = number.y == null ? 0 : number.y.GetHashCode();
        int hashZ = number.z == null ? 0 : number.z.GetHashCode();
        int hashW = number.w == null ? 0 : number.w.GetHashCode();

        return hashX ^ hashY ^ hashZ ^ hashW;           
    }
}

這是我的Message對象List

Message m1 = new Message();
m1.x = 1;
m1.y = "A";
m1.z = "B";
m1.w = "C";

Message m2 = new Message();
m2.x = 1;
m2.y = "A";
m2.z = "B";
m2.w = "C";

Message m3 = new Message();
m3.x = 1;
m3.y = "A";
m3.z = "B";
m3.w = "C";

Message m4 = new Message();
m4.x = 2;
m4.y = "A";
m4.z = "B";
m4.w = "C";

Message m5 = new Message();
m5.x = 3;
m5.y = "W";
m5.z = "D";
m5.w = "C";

Message m6 = new Message();
m6.x = 4;
m6.y = "S";
m6.z = "F";
m6.w = "R";

List<Message> collection = new List<Message>();
collection.Add(m1);
collection.Add(m2);
collection.Add(m3);
collection.Add(m4);
collection.Add(m5);

collection.Distinct(new MessageComparer());

當我調用Distinct()方法時, collection中的元素數量是相同的。

嘗試這個:

var distinct = collection.Distinct(new MessageComparer());

然后對之后的任何內容使用distinct

看起來您忘記了IEnumerable<>的不可變性質。 沒有任何 LINQ 方法實際上會更改原始變量。 相反,它們返回包含表達式結果的IEnuerable<T> s。 例如,讓我們考慮一個簡單的List<string> original內容,其內容為{ "a", "a", "b", "c" }

現在,讓我們調用original.Add("d"); . 該方法沒有返回值(它是void )。 但是如果我們打印出original的內容,我們會看到{ "a", "a", "b", "c", "d" }

另一方面,讓我們現在調用original.Skip(1) 此方法確實有一個返回值,即IEnumerable<string>類型之一。 它是一個 LINQ 表達式,不會對原始集合執行任何副作用。 因此,如果我們調用它並查看original ,我們將看到{ "a", "a", "b", "c", "d" } 但是,該方法的結果將是{ "a", "b", "c", "d" } 如您所見,結果跳過了一個元素。

這是因為 LINQ 方法接受IEnumerable<T>作為參數。 因此,他們沒有實現原始列表的概念。 您可以通過擴展方法傳遞ReadOnlyCollection ,他們仍然可以通過它進行評估。 然后,他們無法更改原始集合,因為原始集合可以以多種方式編寫。

所有這些,但以表格形式。 每行都以原始{ "a", "a", "b", "c" }開頭:

Context     Example function    Immutable?    Returned Value     Collection after calling
Collection  Add("d")            No            (void)             { "a", "a", "b", "c", "d" }:
LINQ        Skip(1)             Yes           { "a", "b", "c" }  { "a", "a", "b", "c" }:

IEqualityComparer是一個用於判斷對象是否相等的接口。 我們將在一個示例中看到這一點,我們必須在一個集合中找到不同的對象。 該接口將實現Equals(T obj1,T obj2)

abstract public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { set; get; }
}

public enum SortType
{
    ByID,
    BySalary
}

public class EmployeeDistinctEquality : IEqualityComparer<Employee>
{
    public EmployeeDistinctEquality()
    {

    }

    public bool Equals(Employee x, Employee y)
    {
        if (x == null && y == null)
            return true;
        else if (x == null || y == null)
            return false;
        else if (x.Id == y.Id)
            return true;
        else
            return false;
    }

    public int GetHashCode(Employee obj)
    {
        return obj.Id.GetHashCode();
    }
}

有關更多詳細信息,請參閱此鏈接:

http://dotnetvisio.blogspot.in/2015/12/usage-of-icomparer-icomparable-and.html

您不需要實現IEqualityComparer

public class Message
{
    protected bool Equals(Message other)
    {
        return string.Equals(x, other.x) && string.Equals(y, other.y) && string.Equals(z, other.z) && string.Equals(w, other.w);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((Message) obj);
    }

    public override int GetHashCode()
    {
        unchecked //Ignores overflows that can (should) occur
        {
            var hashCode = x;
            hashCode = (hashCode*397) ^ (y != null ? y.GetHashCode() : 0);
            hashCode = (hashCode*397) ^ (z != null ? z.GetHashCode() : 0);
            hashCode = (hashCode*397) ^ (w != null ? w.GetHashCode() : 0);
            return hashCode;
        }
    }

    public int x { get; set; }
    public string y { get; set; }
    public string z { get; set; }
    public string w { get; set; }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM