[英]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.