Về cơ bản, tôi đã sau cho đến nay:Làm thế nào tôi nên đi về việc thực hiện Object.GetHashCode() cho sự bình đẳng phức tạp?
class Foo {
public override bool Equals(object obj)
{
Foo d = obj as Foo ;
if (d == null)
return false;
return this.Equals(d);
}
#region IEquatable<Foo> Members
public bool Equals(Foo other)
{
if (this.Guid != String.Empty && this.Guid == other.Guid)
return true;
else if (this.Guid != String.Empty || other.Guid != String.Empty)
return false;
if (this.Title == other.Title &&
this.PublishDate == other.PublishDate &&
this.Description == other.Description)
return true;
return false;
}
}
Vì vậy, vấn đề là thế này: Tôi có một tổ chức phi Bắt buộc điền vào Guid
, mà là một định danh duy nhất. Nếu điều này không được thiết lập, thì tôi cần phải cố gắng xác định sự bình đẳng dựa trên các số liệu ít chính xác hơn như là một nỗ lực để xác định xem hai đối tượng có bình đẳng không. Điều này làm việc tốt, nhưng nó làm cho GetHashCode()
lộn xộn ... Làm thế nào tôi nên đi về nó? Triển khai ngây thơ sẽ giống như sau:
public override int GetHashCode() {
if (this.Guid != String.Empty)
return this.Guid.GetHashCode();
int hash = 37;
hash = hash * 23 + this.Title.GetHashCode();
hash = hash * 23 + this.PublishDate.GetHashCode();
hash = hash * 23 + this.Description.GetHashCode();
return hash;
}
Nhưng cơ hội của hai loại băm va chạm là gì? Chắc chắn, tôi sẽ không mong đợi nó là 1 in 2 ** 32
. Đây có phải là một ý tưởng tồi, và nếu có, tôi nên làm như thế nào?
Điều quan trọng hơn là thuật toán băm của bạn đồng ý với thuật toán bình đẳng của bạn so với phân phối đồng đều. Hãy nhớ rằng, mục đích của băm là chỉ để có được một bản phân phối tốt trong một bảng băm; miễn là bạn không ồ ạt xiên vào một thùng cụ thể, tỷ lệ cược là tốt, bạn sẽ ổn thôi. Nếu bạn quan tâm, hãy chọn một kịch bản hợp lý mà người tiêu dùng của đối tượng của bạn có khả năng gặp phải - giả sử, đặt vài trăm từ trong từ điển, nếu điều đó hợp lý - và thực hiện một số thử nghiệm perf để xem bạn có chấp nhận được không các kết quả. –
Điều tôi từng thấy trong thực tế sử dụng là ~ 200, nhưng việc sử dụng điển hình là <30, vì vậy bạn có thể đúng. –
Heck, với dưới 30 mục, tìm kiếm tuyến tính trong danh sách được liên kết có thể là một người thực hiện hợp lý. Bạn có thể trả lại mã băm bằng 0, luôn có 100% cơ hội va chạm và vẫn nhận được hiệu suất chấp nhận được. Điểm của việc phân phối mã băm tốt là tạo ra quy mô hiệu suất khi kích thước từ điển trở nên lớn. Bạn có thể có một bản phân phối tệ hại và vẫn nhận được kết quả tốt nếu bạn chỉ sẽ đặt một số lượng nhỏ các mục trong bảng. –