2010-09-22 39 views
11

Tôi đã có một kiểu generic:Tại sao mã này sẽ phàn nàn về "tính xác thực của định nghĩa kiểu chung"?

class DictionaryComparer<TKey, TValue> : IEqualityComparer<IDictionary<TKey, TValue>> 

Và một phương pháp nhà máy mà sẽ (nên) tạo ra một thể hiện của lớp này cho một loại từ điển nhất định.

private static IEqualityComparer<T> CreateDictionaryComparer<T>() 
    { 
     Type def = typeof(DictionaryComparer<,>); 
     Debug.Assert(typeof(T).IsGenericType); 
     Debug.Assert(typeof(T).GetGenericArguments().Length == 2); 

     Type t = def.MakeGenericType(typeof(T).GetGenericArguments()); 

     return (IEqualityComparer<T>)Activator.CreateInstance(t); 
    } 

Tước tất cả các nội dung không liên quan - ngay cả mã này cũng ném cùng một ngoại lệ.

private static object CreateDictionaryComparer() 
{ 
    Type def = typeof(DictionaryComparer<,>); 

    Type t = def.MakeGenericType(new Type[] { typeof(String), typeof(object) }); 

    return Activator.CreateInstance(t); 
} 

Thông báo xác nhận vì vậy tôi biết rằng T là chung và có hai đối số chung chung. Dòng có MakeGenericType tuy nhiên, ngoại trừ:

Số lượng đối số chung được cung cấp không bằng với định nghĩa chung của định nghĩa loại chung.

tên Parameter: instantiation

tôi đã thực hiện việc này trong quá khứ và cho cuộc sống của tôi không thể tìm ra lý do tại sao điều này không làm việc trong trường hợp này. (cộng với tôi phải có Google arity).

+0

Bạn đang chuyển từ 'T' sang' CreateDictionaryComparer' như thế nào? Tôi đã cố gắng đi qua 'CreateDictionaryComparer >()' và điều này làm việc tốt cho tôi (sử dụng Mono C# compiler phiên bản 1.9.1.0). –

+0

Tôi đã có DictionaryComparer như một lớp bên trong với một cái mà chính nó là chung chung. Hãy nghĩ rằng đã được hosing lên các công trình. – dkackman

+0

Chỉ cần ra khỏi tò mò, bạn có thể cung cấp đầy đủ (không) mẫu để tôi có thể thử nó trên trình biên dịch của tôi? –

Trả lời

13

Đã tìm ra.

Tôi đã có DictionaryComparer được khai báo là lớp bên trong. Tôi chỉ có thể giả định rằng MakeGenericType muốn thực hiện một số Query<T>.DictionaryComparer<string,object> và không được cung cấp T.

Không đang

class Program 
{ 
    static void Main(string[] args) 
    { 
     var q = new Query<int>(); 
     q.CreateError(); 
    } 
} 

public class Query<TSource> 
{ 
    public Query() 
    {  
    } 

    public object CreateError() 
    { 
     Type def = typeof(DictionaryComparer<,>); 

     Type t = def.MakeGenericType(new Type[] { typeof(String), typeof(object) }); 

     return Activator.CreateInstance(t); 
    } 

    class DictionaryComparer<TKey, TValue> : IEqualityComparer<IDictionary<TKey, TValue>> 
    { 
     public DictionaryComparer() 
     { 
     } 

     public bool Equals(IDictionary<TKey, TValue> x, IDictionary<TKey, TValue> y) 
     { 
      if (x.Count != y.Count) 
       return false; 

      return GetHashCode(x) == GetHashCode(y); 
     } 

     public int GetHashCode(IDictionary<TKey, TValue> obj) 
     { 
      int hash = 0; 
      unchecked 
      { 
       foreach (KeyValuePair<TKey, TValue> pair in obj) 
       { 
        int key = pair.Key.GetHashCode(); 
        int value = pair.Value != null ? pair.Value.GetHashCode() : 0; 
        hash ^= key^value; 
       } 
      } 
      return hash; 
     } 
    } 
} 
+0

Chỉ cần ra khỏi tò mò, bạn có thể cung cấp đầy đủ (không) mẫu để tôi có thể thử nó trên trình biên dịch của tôi? –

+0

Hãy xem liệu tôi có thể xóa các nội dung không liên quan ra một ví dụ có thể biên dịch được không – dkackman

+0

Cảm ơn! Di chuyển 'DictionaryComparer ' bên ngoài lớp container chung 'Truy vấn ' sửa vấn đề. Tôi đã thử nghiệm và bạn có thể lồng 'DictionaryComparer ', không nằm trong một lớp chung khác. Cũng muốn đảm bảo rằng trình biên dịch và môi trường thời gian chạy của tôi hoạt động giống như của bạn. –

1

CLR tạo ra một cấu trúc dữ liệu nội bộ cho mỗi và tất cả các loại được sử dụng bởi một cấu trúc dữ liệu application.These được gọi là đối tượng kiểu. Một kiểu với các tham số kiểu chung được gọi là kiểu mở và CLR không cho phép bất kỳ thể hiện nào của kiểu mở được xây dựng (tương tự như cách CLR ngăn cản một thể hiện của một loại giao diện đang được xây dựng).

Thay đổi Loại t = def.MakeGenericType (loại mới [] {typeof (String), typeof (object)});
trên
Loại t = def.MakeGenericType (loại mới [] {typeof (TSource), typeof (String), typeof (object)});

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