2011-02-04 13 views
18

Có một số địa điểm ở BCL nơi có thể sử dụng IEqualityComparer. Giống như Enumerable.Contains hoặc Dictionary Constructor. Tôi có thể cung cấp bộ so sánh nếu tôi không hài lòng với số default.Có loại "ReferenceComparer" nào trong .NET không?

Đôi khi tôi muốn biết liệu bộ sưu tập có chứa mà đối tượng rất mà tôi có tham chiếu đến không. Không phải cái được coi là "bình đẳng" theo bất kỳ nghĩa nào khác.
Câu hỏi đặt ra là: liệu có tồn tại sự so sánh bình đẳng tiêu chuẩn trong BCL chỉ dựa trên phương pháp ReferenceEquals không?

Một trong đó tôi đã viết bản thân mình là thế này:

class ReferenceComparer<T> : IEqualityComparer<T> where T : class 
{ 
    private static ReferenceComparer<T> m_instance; 

    public static ReferenceComparer<T> Instance 
    { 
     get 
     { 
      return m_instance ?? (m_instance = new ReferenceComparer<T>()); 
     } 
    } 

    public bool Equals(T x, T y) 
    { 
     return ReferenceEquals(x, y); 
    } 

    public int GetHashCode(T obj) 
    { 
     return RuntimeHelpers.GetHashCode(obj); 
    } 
} 

tôi không kiểm tra nó kỹ lưỡng cũng không coi nhiều kịch bản, nhưng có vẻ như để làm cho Enumerable.ContainsDictionary khá hạnh phúc.

+2

Thật không may là tất cả các bộ sưu tập này được viết theo cách Java-esque, yêu cầu bạn viết một lớp thực hiện một giao diện cụ thể. Nếu chỉ họ cho phép bạn vượt qua trong một đại biểu để xác định toán tử so sánh, bạn có thể truyền trực tiếp 'object.ReferenceEquals'. Tôi đoán đó là bởi vì hai phương pháp là cần thiết (so sánh và hashcode). –

+0

Vì tôi hiểu nó, mặc dù, đối tác Java với 'IEqualityComparer' không có' GetHashCode', vì vậy nó * có thể * được thực hiện như một đại biểu trong Java nếu các đại biểu được hỗ trợ Java. – Gabe

+1

@Ben xem câu trả lời của orip: http: // stackoverflow.com/questions/98033/wrap-a-delegate-in-an-iequalitycomparer/1239337 # 1239337 –

Trả lời

17

Theo như tôi biết, BCL không hiển thị bất kỳ loại công khai nào triển khai IEqualityComparer<T> với mức độ tham chiếu bằng .NET 4.0.

Tuy nhiên, có làm xuất hiện như một loạt các loại nội bộ mà làm được điều này, chẳng hạn như:

  • System.Dynamic.Utils.ReferenceEqualityComparer<T> (trong System.Core)
  • System.Xaml.Schema.ReferenceEqualityComparer<T> (trong System.Xaml).

tôi đã xem xét việc triển khai của hai loại với phản xạ, và bạn sẽ được hạnh phúc để biết rằng cả hai chúng xuất hiện để được thực hiện theo một cách mà là hầu như giống hệt nhau như của bạn, ngoại trừ việc chúng không sử dụng quá trình khởi tạo lười biếng cho cá thể tĩnh (chúng tạo ra nó trong hàm dựng tĩnh cho kiểu). Chỉ có thể có 'vấn đề' tôi có thể nghĩ đến với việc triển khai của bạn là khởi tạo lười biếng không an toàn cho luồng, nhưng vì các trường hợp là 'rẻ' và không nắm giữ bất kỳ trạng thái nào, không nên tạo bất kỳ lỗi hoặc vấn đề hiệu suất lớn. Nếu bạn muốn thực thi kiểu mẫu đơn, bạn sẽ phải làm điều đó đúng cách.

+0

Cảm ơn bạn đã đề cập đến thất bại khởi tạo lười biếng của tôi. Đối với lớp này có vẻ có ý nghĩa để khởi tạo cá thể trong hàm dựng tĩnh. Tuy nhiên, nhờ bạn, tôi sẽ không phạm sai lầm tương tự ở bất cứ nơi nào khác. –

+0

@ alpha-chuột: Chúc mừng. Tôi sẽ nói rằng tôi sẽ không cảm thấy có nghĩa vụ phải làm cho một lớp học an toàn chỉ vì lợi ích của nó, trừ khi tôi có ý định * sử dụng * nó theo cách đòi hỏi nó. – Ani

+0

Ngoài ra còn có 'System.Data.Entity.Infrastructure.ObjectReferenceEqualityComparer'. –

2

Tôi kết thúc bằng cách sử dụng giải pháp này cũng như tôi không thể tìm thấy bất kỳ giải pháp thay thế nào.

Để khắc phục việc triển khai không an toàn, bạn có thể dễ dàng sử dụng bộ khởi động tĩnh.

public static ReferenceComparer<T> Instance => new ReferenceComparer<T>(); 

(xin lỗi vì câu trả lời thay vì nhận xét cho chủ đề bỏ phiếu, tôi chưa có quyền nhận xét).

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