2012-03-14 28 views
9

Tôi tự thấy mình tự ghi đè Equals()GetHashCode() thường xuyên để thực hiện ngữ nghĩa. Điều đó dẫn đến mã lặp đi lặp lại để viết và mong manh để duy trì (thuộc tính được thêm vào và một/cả hai ghi đè không được cập nhật).Đơn giản hóa các giá trị bằng(), GetHashCode() trong C# để duy trì tốt hơn

Mã này kết thúc lên tìm kiếm một cái gì đó như thế này (bình luận về việc thực hiện đều được chào đón):

public override bool Equals(object obj) 
{ 
    if (object.ReferenceEquals(this, obj)) return true; 

    MyDerived other = obj as MyDerived; 

    if (other == null) return false; 

    bool baseEquals = base.Equals((MyBase)other); 
    return (baseEquals && 
     this.MyIntProp == other.MyIntProp && 
     this.MyStringProp == other.MyStringProp && 
     this.MyCollectionProp.IsEquivalentTo(other.MyCollectionProp) && // See http://stackoverflow.com/a/9658866/141172 
     this.MyContainedClass.Equals(other.MyContainedClass)); 
} 

public override int GetHashCode() 
{ 
    int hashOfMyCollectionProp = 0; 
    // http://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/ 
    // BUT... is it worth the extra math given that elem.GetHashCode() should be well-distributed? 
    int bitSpreader = 31; 
    foreach (var elem in MyCollectionProp) 
    { 
     hashOfMyCollectionProp = spreader * elem.GetHashCode(); 
     bitSpreader *= 31; 
    } 
    return base.GetHashCode()^//^is a good combiner IF the combined values are well distributed 
     MyIntProp.GetHashCode()^
     (MyStringProp == null ? 0 : MyStringProp.GetHashValue())^
     (MyContainedClass == null ? 0 : MyContainedClass.GetHashValue())^
     hashOfMyCollectionProp; 
} 

Câu hỏi của tôi

  1. Sản phẩm mẫu âm thanh thực hiện?
  2. Có đủ không khi các giá trị thành phần đóng góp được phân phối tốt? Tôi có cần phải nhân với 31-to-the-N khi kết hợp các yếu tố thu thập được cho băm của họ được phân phối tốt không?
  3. Dường như mã này có thể được tóm tắt thành mã sử dụng sự phản chiếu để xác định các thuộc tính công khai, xây dựng cây biểu thức khớp với giải pháp được mã hóa bằng tay và thực thi cây biểu thức nếu cần. Cách tiếp cận đó có vẻ hợp lý không? Có triển khai hiện tại ở đâu đó không?
+2

Tại sao downvote (hơn một năm sau khi công bố)? Câu hỏi là rất hợp pháp. Nếu có điều gì đó sai trái, hãy nói gì. –

Trả lời

4

MSDN thực tế không nói "không quá tải Bằng et al cho các loại có thể thay đổi". Nó được sử dụng để nói rằng, nhưng bây giờ nó nói:

Khi bạn định nghĩa một lớp học hoặc struct, bạn quyết định xem nó có ý nghĩa để tạo ra một định nghĩa tùy chỉnh của giá trị bình đẳng (hoặc tương đương) cho loại. Thông thường, bạn thực hiện bình đẳng giá trị khi các đối tượng thuộc loại được dự kiến ​​sẽ được thêm vào bộ sưu tập của một số loại hoặc khi mục đích chính của chúng là lưu trữ một nhóm trường hoặc thuộc tính.

http://msdn.microsoft.com/en-us/library/dd183755.aspx

Tuy nhiên, có những phức tạp xung quanh ổn định của mã băm trong khi một đối tượng tham gia trong một bộ sưu tập băm (Dictionary<T,U>, HashSet<T>, vv).

tôi quyết định lựa chọn tốt nhất của cả hai thế giới, như được nêu ở đây:

https://stackoverflow.com/a/9752155/141172

1

tôi thấy tự trọng của tôi Equals() và GetHashCode() thường xuyên

  • MSDN nói: không quá tải Equals et al với nhiều loại có thể thay đổi

Có đủ không khi các giá trị thành phần đóng góp được phân phối tốt?

  • Có, nhưng không phải lúc nào cũng được phân phối tốt. Xem xét int thuộc tính. Thay đổi với một số số nguyên tố nhỏ (nhỏ) được khuyên dùng.
+0

MSDN nói ở đâu? Tôi đã cố gắng googling văn bản theo nghĩa đen và chỉ tìm thấy câu hỏi này. –

+0

Ngoài ra ... để có một ví dụ đơn giản về nơi tôi thấy tiện ích trong trọng số bằng (nhưng có lẽ tôi đang thiếu một cái gì đó), làm thế nào bạn sẽ thực hiện một bài kiểm tra đơn vị mà không ghi đè Equals cho 'MyDerived expected = new MyDerived() {/* Khởi tạo * /}; MyDerived actual = DoSomeTest(); Assert.AreEqual (dự kiến, thực tế) '? –

+0

Và liên quan đến^... trong trường hợp của tôi, mỗi giá trị XOR là kết quả của GetHashCode(), nên được phân phối hợp lý. Khi thực hiện, bạn có thấy những sai sót trong cách tôi sử dụng ^? Bạn sẽ nhân các phần tử thu thập bởi một số nguyên tố ngay cả khi băm của mỗi phần tử thu thập là kết quả của GetHashCode()? –

0

Có lẽ tôi nhầm lẫn ở đây, nhưng không nên về null kiểm tra trở lại 1 thay vì 0 trong ghi đè GetHashCode?

Vì vậy

MyStringProp == null ? 0 : MyStringProp.GetHashValue() 

nên

MyStringProp == null ? 1 : MyStringProp.GetHashValue() 
Các vấn đề liên quan