2010-09-22 6 views
11

Mam typu rodzajowego:Dlaczego ten kod narzekałby na "ogólną definicję typu"?

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

oraz metody fabryki, które będą (powinny) utworzyć instancję tej klasy dla danego rodzaju słownika.

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); 
    } 

Pozbycie się wszystkich obcych rzeczy - nawet ten kod generuje ten sam wyjątek.

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

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

    return Activator.CreateInstance(t); 
} 

The twierdzi przechodzą więc wiem, że T ma charakter ogólny i ma dwa argumenty rodzajowe. Linia z numerem MakeGenericType, ale z wyjątkiem:

Liczba podanych ogólnych argumentów nie jest równa ogólnej definicji typu.

Nazwa parametru: instancji

robiłem takie rzeczy w przeszłości i dla życia mnie nie mogę zrozumieć, dlaczego to nie działa w tym przypadku. (plus miałem do Google arity).

+0

Co przechodzisz jako 'T' do' CreateDictionaryComparer'? Próbowałem przekazanie 'CreateDictionaryComparer >()' i to działa dobrze dla mnie (przy użyciu kompilatora Mono C# w wersji 1.9.1.0). –

+0

Miałem DictionaryComparer jako klasę wewnętrzną do tej, która sama jest generyczna. Pomyśl, że to robota. – dkackman

+0

Po prostu z ciekawości, czy mógłbyś podać pełną (uszkodzoną) próbkę, aby móc ją wypróbować na moim kompilatorze? –

Odpowiedz

13

Wyliczyłem to.

Posiadałem DictionaryComparer zadeklarowaną jako wewnętrzna klasa. Mogę tylko założyć, że MakeGenericType chciał zrobić Query<T>.DictionaryComparer<string,object> i nie został dostarczony T.

przypadku braku kodu

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

Po prostu z ciekawości, czy mógłbyś podać pełną (uszkodzoną) próbkę, aby móc wypróbować ją na moim kompilatorze? –

+0

Zobacz, czy uda mi się usunąć niepowiązane elementy z kompilowanym przykładem. – dkackman

+0

Dzięki! Przeniesienie 'DictionaryComparer ' poza ogólną klasą kontenera 'Query ' rozwiązuje problem. Eksperymentowałem i można zagnieździć 'DictionaryComparer ', po prostu nie wewnątrz innej klasy ogólnej. Chciałem również upewnić się, że mój kompilator i środowisko wykonawcze zachowywały się tak samo jak twoje. –

1

CLR tworzy wewnętrzną strukturę danych dla każdego rodzaju użytkowania przez application.These struktur danych nazywane są obiektami typu. Typ o typowych parametrach nazywany jest typem otwartym, a CLR nie pozwala na zbudowanie dowolnej instancji typu otwartego (podobnie do tego, w jaki sposób CLR zapobiega budowaniu instancji typu interfejsu).

Zmiana Typ t = def.MakeGenericType (nowy typ [] {typof (ciąg), typeof (obiekt)}); na
Typ t = def.MakeGenericType (nowy typ [] {typeof (TSource), typeof (String), typeof (object)});

Powiązane problemy