2013-01-31 20 views
8

Xem xét T = chuỗi.EqualityComparer <T> .Default hoạt động trong nội bộ như thế nào?

tôi tò mò nếu nó sử dụng một cái gì đó như: typeof(EqualityComparer<T>).GetInterface("IEqualityComparer<T>");

gợi ý Bất kỳ ..

+0

Tại sao nó sẽ nói 'GetInterface' để lấy đối tượng' System.Type' cho giao diện mà nó thực hiện? Điều đó sẽ hữu ích như thế nào? Nó chỉ có thể nói 'typeof (IEqualityComparer )' nếu nó cần loại somhow, nhưng nó không cần điều đó. Nó cần trả về một thể hiện của 'EqualityComparer ' mà chúng ta có thể sử dụng. Vì lớp là 'abstract', điều này liên quan đến việc tạo ra một cá thể của một số lớp dẫn xuất không trừu tượng và trả về nó. Nhưng có lẽ bạn thực sự hỏi đối tượng trả về hoạt động như thế nào? (Ít nhất đó là những gì tôi trả lời dưới đây.) –

Trả lời

9

Courtesy of Reflector:

public static EqualityComparer<T> Default 
{ 
    get 
    { 
     EqualityComparer<T> defaultComparer = EqualityComparer<T>.defaultComparer; 
     if (defaultComparer == null) 
     { 
      defaultComparer = EqualityComparer<T>.CreateComparer(); 
      EqualityComparer<T>.defaultComparer = defaultComparer; 
     } 
     return defaultComparer; 
    } 
} 

private static EqualityComparer<T> CreateComparer() 
{ 
    RuntimeType c = (RuntimeType) typeof(T); 
    if (c == typeof(byte)) 
    { 
     return (EqualityComparer<T>) new ByteEqualityComparer(); 
    } 
    if (typeof(IEquatable<T>).IsAssignableFrom(c)) 
    { 
     return (EqualityComparer<T>) RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType) typeof(GenericEqualityComparer<int>), c); 
    } 
    if (c.IsGenericType && (c.GetGenericTypeDefinition() == typeof(Nullable<>))) 
    { 
     RuntimeType type2 = (RuntimeType) c.GetGenericArguments()[0]; 
     if (typeof(IEquatable<>).MakeGenericType(new Type[] { type2 }).IsAssignableFrom(type2)) 
     { 
      return (EqualityComparer<T>) RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType) typeof(NullableEqualityComparer<int>), type2); 
     } 
    } 
    if (c.IsEnum && (Enum.GetUnderlyingType(c) == typeof(int))) 
    { 
     return (EqualityComparer<T>) RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType) typeof(EnumEqualityComparer<int>), c); 
    } 
    return new ObjectEqualityComparer<T>(); 
} 

Như bạn có thể thấy nếu T = chuỗi nó sẽ trở lại GenericEqualityComparer<string>.

+0

Đánh tôi với nó: P –

+2

Tôi không biết nếu điều này là hữu ích. Nó cho thấy lớp không công khai nào đang được sử dụng phía sau khung cảnh, nhưng nó không cung cấp thông tin về cách thức hoạt động của lớp 'GenericEqualityComparer ' không công khai. Vì vậy, những người quan tâm những gì thực hiện cụ thể của lớp trừu tượng là _named_? –

2

EqualityComparer<T>.Default công trình bằng cách gọi phương pháp virtualEquals(object)GetHashCode() được định nghĩa bởi System.Object nhưng có thể hoặc có thể không được ghi đè bởi T.

Lưu ý rằng vì metods là virtual, nên việc triển khai lớp có nguồn gốc cao hơn T có thể được sử dụng. Ví dụ:

EqualityComparer<object>.Default 
    .Equals(new Uri("http://example.com/"), new Uri("http://example.com/")) 

sẽ trở lại true, ngay cả khi

Object.ReferenceEquals(new Uri("http://example.com/"), new Uri("http://example.com/")) 

(object)new Uri("http://example.com/") == (object)new Uri("http://example.com/") 

cả trở false.

Trong trường hợp Tstring, lớp System.String làm quá tải hai phương pháp được đề cập và sử dụng so sánh thứ tự. Vì vậy, trong trường hợp này, nó phải tương đương với System.StringComparer.Ordinal. Và tất nhiên string là một lớp học sealed, vì vậy không có lớp học nào khác có thể lấy được từ string và ghi đè EqualsGetHashCode theo một cách lạ.

+1

Ngoài ra - Lợi thế là lần đầu tiên kiểm tra nếu T thực hiện 'IEquatable ' và nếu vậy, hãy gọi thực hiện thay vào đó, tránh phần trên đầu boxing. Điều này đặc biệt hữu ích trong các phương thức chung: 'static bool Foo (T x, T y) { bool same = EqualityComparer .Default.Equals (x, y);' –

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