2013-05-21 25 views
10

Tôi có một trường hợp mà tôi cần phải lấy một loạt các mặt hàng trên rõ rệt, nhưng nguồn của tôi là một tập hợp các đối tượng với hai thuộc tính, như thế này:thực hiện IEqualityComparer <T> trên một đối tượng với hai thuộc tính trong C#

public class SkillRequirement 
{ 
    public string Skill { get; set; } 
    public string Requirement { get; set; } 
} 

tôi cố gắng để có được một bộ sưu tập như sau:

SkillRequirementComparer sCom = new SkillRequirementComparer(); 

var distinct_list = source.Distinct(sCom); 

tôi cố gắng để thực hiện một IEqualityComparer<T> cho điều này, nhưng tôi đã giảm bối rối ở phương pháp GetHashCode().

Lớp cho Comparer:

public class SkillRequirementComparer : IEqualityComparer<SkillRequirement> 
{ 
    public bool Equals(SkillRequirement x, SkillRequirement y) 
    { 
     if (x.Skill.Equals(y.Skill) && x.Requirement.Equals(y.Requirement)) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 

    public int GetHashCode(SkillRequirement obj) 
    { 
     //????? 
    } 
} 

Thông thường tôi sẽ chỉ sử dụng GetHashCode() trên một bất động sản, nhưng vì tôi so sánh về hai thuộc tính, tôi là một chút lúng túng về những gì để làm. Tôi có làm bất cứ điều gì sai, hoặc thiếu một cái gì đó thực sự rõ ràng?

+0

Hãy cẩn thận khi sử dụng một 'GetHashCode()' có nguồn gốc từ các trường có thể thay đổi! Nếu bạn đặt đối tượng trong bộ sưu tập băm rồi thay đổi một trong các trường - ouch. Tôi đề nghị làm cho nó không thay đổi. –

+0

Giá trị của thuộc tính là orginally từ cơ sở dữ liệu, trong đó các cột không cho phép null, cũng có kiểm tra chuỗi rỗng hoặc trống trước khi đối tượng được thêm vào danh sách nguồn, vì vậy nó không phải là mối quan tâm: ^) –

Trả lời

10

Bạn có thể thực hiện GetHashCode theo cách sau:

public int GetHashCode(SkillRequirement obj) 
{ 
    unchecked 
    { 
     int hash = 17; 
     hash = hash * 23 + obj.Skill.GetHashCode(); 
     hash = hash * 23 + obj.Requirement.GetHashCode(); 
     return hash; 
    } 
} 

originally từ J.Skeet

Nếu các thuộc tính có thể null bạn nên tránh một NullReferenceException, ví dụ:

int hash = 17; 
hash = hash * 23 + (obj.Skill ?? "").GetHashCode(); 
hash = hash * 23 + (obj.Requirement ?? "").GetHashCode(); 
return hash; 
+1

(Trên thực tế nó ban đầu từ Josh Bloch;) –

+0

Không phải là một ý tưởng hay. Các thuộc tính đó có thể thay đổi. –

+0

@ UfukHacıoğulları: Bạn có thể chỉ định phản đối của mình không? –

1

Tôi muốn liên kết vị trí tràn ngăn xếp sau đây TS quá mặc dù câu hỏi đã được trả lời ..

GetHashCode -

Why is it important to override GetHashCode when Equals method is overridden?

Ngoài ra, trong các câu trả lời trên Tim Schmelter nói the properties can be null you should avoid a NullReferenceException

int hash = 17; 
hash = hash * 23 + (obj.Skill ?? "").GetHashCode(); 
hash = hash * 23 + (obj.Requirement ?? "").GetHashCode(); 
return hash; 

IEqualityComparer -

  1. What is the difference between using IEqualityComparer and Equals/GethashCode Override
  2. What's the role of GetHashCode in the IEqualityComparer in .NET?
  3. How and when to use IEqualityComparer in C#

IEquatable - What's the difference between IEquatable and just overriding Object.Equals()?

Equals - Guidelines for Overloading Equals()

class TwoDPoint : System.Object 
{ 
    public readonly int x, y; 

    public TwoDPoint(int x, int y) //constructor 
    { 
     this.x = x; 
     this.y = y; 
    } 

    public override bool Equals(System.Object obj) 
    { 
     // If parameter is null return false. 
     if (obj == null) 
     { 
      return false; 
     } 

     // If parameter cannot be cast to Point return false. 
     TwoDPoint p = obj as TwoDPoint; 
     if ((System.Object)p == null) 
     { 
      return false; 
     } 

     // Return true if the fields match: 
     return (x == p.x) && (y == p.y); 
    } 

    public bool Equals(TwoDPoint p) 
    { 
     // If parameter is null return false: 
     if ((object)p == null) 
     { 
      return false; 
     } 

     // Return true if the fields match: 
     return (x == p.x) && (y == p.y); 
    } 

    public override int GetHashCode() 
    { 
     //return x^y; 
    } 
} 
Các vấn đề liên quan