2009-07-22 53 views
9

Cách tốt nhất để tạo phương thức GetHashCode của riêng bạn cho một lớp trong C# là gì? Giả sử tôi có một lớp đơn giản (ghi đè phương thức Bằng), như sau:Tạo phương thức GetHashCode trong C#

class Test 
    { 
     public string[] names; 

     public double[] values; 

     public override bool Equals(object obj) 
     { 
     return (obj is Test) && this.Equals((Test)obj); 
     } 

     public bool Equals(Test t) 
     { 
     return names.Equals(t.names) && values.Equals(t.values); 
     } 
    } 

Tôi có nên sử dụng mã mặc định cho phương pháp GetHashCode không?

public override int GetHashCode() 
    { 
    return base.GetHashCode(); 
    } 

Tôi có nên căn cứ vào nội dung lớp học của mình không?

public override int GetHashCode() 
    { 
    return names.GetHashCode() + values.GetHashCode() ; 
    } 

Hoặc tôi có nên làm gì khác không?

+0

Bạn không ghi đè đúng ở đây. – jjnguy

+0

Trên thực tế, tôi nghĩ rằng nó sẽ dẫn đến stackoverflow. – jjnguy

+0

Không, nó sẽ không tràn ngăn xếp. Tuy nhiên, nó cũng không hoạt động. – SLaks

Trả lời

12

System.Array không ghi đè GetHashCode hoặc Equals, để chúng sử dụng bình đẳng tham chiếu. Do đó, bạn không nên gọi cho họ.

Để triển khai GetHashCode, hãy xem this question.

Để triển khai Equals, hãy sử dụng phương thức mở rộng SequenceEqual.

EDIT: Trên Net 2.0, bạn sẽ phải viết phiên bản của riêng bạn SequenceEqual, như thế này:

public static bool SequenceEquals<T>(IList<T> first, IList<T> second) { 
    if (first == second) return true; 
    if (first == null || second == null) return false; 

    if (first.Count != second.Count) return false; 

    for (int i = 0; i < first.Count; i++) 
     if (!first[i].Equals(second[i])) 
      return false; 

    return true; 
} 

Bạn có thể viết nó để có IEnumerable<T> thay vì IList<T>, nhưng nó muốn có phần chậm hơn vì nó sẽ không thể thoát sớm nếu các tham số có kích thước khác nhau.

+0

Cảm ơn phản ứng tuyệt vời và nhanh chóng. Có một thay thế cho SequenceEqual mà làm việc với .NET framework 2.0? –

2

Điều thực sự quan trọng là phải đảm bảo bạn ghi đè .GetHashCode() ở bước bằng .Equals().

Về cơ bản, bạn phải chắc chắn rằng họ xem xét các lĩnh vực tương tự như vậy là không vi phạm đầu tiên trong ba quy tắc của GetHashCode (từ MSDN object.GetHashCode())

Nếu hai vật thể so sánh như bình đẳng, phương pháp GetHashCode cho mỗi đối tượng phải trả lại cùng một giá trị. Tuy nhiên, nếu hai đối tượng không so sánh là bằng nhau, phương thức GetHashCode cho đối tượng hai không phải trả lại các giá trị khác nhau.

Nói cách khác, bạn phải đảm bảo rằng mọi thời gian .Equals xem xét hai trường hợp bằng nhau, chúng cũng sẽ có cùng .GetHashCode().

Như được đề cập bởi người khác ở đây, this question trình bày chi tiết cách triển khai tốt. Trong trường hợp bạn quan tâm, tôi đã viết một vài bài viết trên blog về điều tra mã băm vào đầu năm ngoái. Bạn có thể tìm lời huyên thuyên của tôi here (blog entry đầu tiên tôi đã viết về đề tài này)

1

Có một cuộc thảo luận tốt trong những vấn đề here, và bản cập nhật mới nhất đề cập đến BaseObject abstract class cung cấp bởi SharpArchitecture.

Nếu bạn muốn thêm điều gì đó ad hoc, tôi đã tìm thấy mã ReSharper tạo cho Equals() và GetHashCode() là tốt.

Các vấn đề liên quan