2012-02-22 25 views
5

Tôi cần phải băm với biến thành viên thay vì lớp, vì vậy tôi không kiểm tra xem tham chiếu có trong từ điển hay không. Không ghi đè các giá trị mặc định, nó sẽ không tìm thấy Value giống hệt nhau, nhưng chỉ trả về nếu nó tìm thấy cùng một ví dụ chính xác là HashedType, chẳng hạn như mã này không thành công.Lợi thế của việc tạo ra lớp bên ngoài từ IEqualityComparer <> override GetHashCode và Equals

Dictionary.Add(new HashedType(4)); 
Dictionary.Contains(new HashedType(4)); // fails to find 4 

Định nghĩa của HashedType:

HashedType 
{ 
    public HashedType(Int32 value) { Value = value); } 
    public HashedType(String value) { Value = value); } 
    public object Value; 
    public void Serialize(Serializer s) 
    { 
     if (Value.GetType() == typeof(Int32)) 
     { 
     s.Set<Int32>(0); 
     s.Set<Int32>(Value); 
     } 
     else 
     { 
     s.Set<Int32>(1); 
     s.Set<String>(Value); 
     } 

    } 
} 

Dường như tôi có thể ghi đè GetHashCode() và Equals() để thực hiện điều này cho tôi.

Tuy nhiên, MSDN khuyên tôi nên tạo một lớp riêng biệt mà tôi lấy được từ IEqualityComparer và khởi tạo từ điển của tôi đã sử dụng HashedType với HashedTypeComparer: IEqualityComparer.

Để giúp dễ dàng hơn này, tôi đã bắt nguồn từ điển và tạo

HashedTypeDictionary<U> : Dictionary<T,U> 
{ 
    public HashedTypeDictionary() : base(new HashedTypeComparer()) { } 
    public bool Equals(HashedType a, HashedType b) { return a.Value == b.Value; } 
    publci int GetHashCode(HashedType a) { return a.Value.GetHashCode(); } 
} 

này tất cả dường như contrived.

Lợi thế duy nhất tôi nhận được không thay đổi bằng()?

Ý tôi là, thực sự nói, tôi cũng muốn Bằng so sánh với thành viên đó.

Trả lời

4

Ý tưởng là object.Equals là bình đẳng tự nhiên cho loại đó (và GetHashCode phải khớp với ý tưởng bình đẳng đó). IEqualityComparer được sử dụng khi bạn muốn một sự bình đẳng khác nhau trên cơ sở từng trường hợp cụ thể.

Hãy xem xét ví dụ: string. Các phương pháp Equals & GetHashCode bị ghi đè có so sánh trường hợp nhạy cảm. Nhưng nếu bạn muốn một từ điển mà các phím không phân biệt chữ hoa chữ thường thì sao? Bạn viết một IEqualityComparer không phân biệt chữ hoa chữ thường và chuyển nó vào hàm khởi tạo của từ điển.

Ví dụ của bạn có vẻ như bất kỳ hai trường hợp nào của HashedType sẽ được coi là bình đẳng nếu các thành viên của chúng bằng nhau. Trong trường hợp đó, tôi khuyên bạn nên ghi đè các phương pháp object.Equalsobject.GetHashCode và không viết IEqualityComparer.

3

Lý do bạn chọn cái khác là bạn luôn luôn muốn các phiên bản của một loại nhất định được so sánh bằng một logic nhất định hoặc chỉ trong trường hợp này.

EqualsGetHashCode cung cấp triển khai "đúng" là cho dù hai đối tượng có giá trị lô-gic bằng nhau hay không. IEqualityComparer cho phép bạn ghi đè điều đó trong một trường hợp từng trường hợp và để tách quyền sở hữu (có thể là các bên khác nhau kiểm soát các thực thể so với mã sử dụng chúng).

0

Nếu phần lớn thời gian bạn muốn hành vi từ điển hoạt động theo mặc định, hãy ghi đè GetHashCode và Equals. Ghi nhớ cho điều này để làm việc họ không bao giờ phải thay đổi trong vòng đời của đối tượng - vì vậy nếu họ đang chạy Giá trị sau đó giá trị nên được đặt trong constructor và một tài sản chỉ đọc.

IEqualityComparer thực sự được sử dụng khi bạn muốn so sánh mọi thứ khác nhau trong một phần của chương trình.

2

Hãy tưởng tượng, trong một khoảnh khắc, bạn không tự mình sở hữu lớp cơ bản (tức là nó được tạo bởi một nhóm khác hoặc chỉ được cấp cho bạn dưới dạng nhị phân). Bạn luôn luôn có thể tạo IEqualityComparer. Bạn có thể không có tùy chọn thay đổi EqualsGetHashCode ...

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