2010-09-22 6 views
11

Ich habe einen generischen Typen bekommt:Warum würde sich dieser Code über die "Arity der generischen Typdefinition" beschweren?

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

Und eine Factory-Methode, die eine Instanz dieser Klasse für einen bestimmten Wörterbuchtyp wird (soll) erstellen.

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

Entfernen Sie alle überflüssigen Sachen - auch dieser Code löst die gleiche Ausnahme aus. Behauptet

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

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

    return Activator.CreateInstance(t); 
} 

Der passieren, damit ich weiß, dass T generisch ist und hat zwei generische Argumente. Die Linie mit MakeGenericType excepts jedoch mit:

Die Anzahl der generischen Argumente zur Verfügung gestellt nicht die arity der generischen Typdefinition entsprechen.

Parametername: Instanziierung

Ich habe diese Art der Sache in der Vergangenheit getan und für das Leben von mir kann nicht herausfinden, warum dies nicht in diesem Fall arbeiten. (plus ich musste Google arity).

+0

Was sind vorbei Sie als 'T' zu' CreateDictionaryComparer'? Ich habe versucht, 'CreateDictionaryComparer >()' zu übergeben und das funktioniert gut für mich (mit Mono C# -Compiler Version 1.9.1.0). –

+0

Ich hatte DictionaryComparer als eine innere Klasse zu einer, die selbst generisch ist. Denken Sie, dass das die Arbeiten verschloss. – dkackman

+0

Nur aus Neugier, könnten Sie das vollständige (fehlgeschlagene) Beispiel bereitstellen, damit ich es auf meinem Compiler ausprobieren kann? –

Antwort

13

es herausgefunden.

Ich hatte DictionaryComparer als innere Klasse deklariert. Ich kann nur annehmen, dass MakeGenericType ein Query<T>.DictionaryComparer<string,object> machen wollte und nicht T zur Verfügung gestellt.

Andernfalls Code

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

Nur aus Neugier, könnten Sie das vollständige (fehlerhafte) Beispiel bereitstellen, damit ich es auf meinem Compiler ausprobieren kann? –

+0

Lass mich sehen, ob ich nicht verwandtes Zeug aus einem kompilierbaren Beispiel entfernen kann – dkackman

+0

Danke! Das Verschieben von 'DictionaryComparer ' außerhalb der generischen Container-Klasse 'Query ' behebt das Problem. Ich habe experimentiert und kann 'DictionaryComparer ' verschachteln, nur nicht in einer anderen generischen Klasse. Ich wollte auch sicherstellen, dass sich Compiler und Laufzeitumgebung genauso verhalten wie Ihre. –

1

CLR erstellt eine interne Datenstruktur für jeden Typ in Verwendung durch eine application.These Datenstrukturen werden Typobjekte genannt. Ein Typ mit generischen Typ Parameter ist ein offener Typ und der CLR nicht zulässt, dass jede Instanz eines offenen Typ genannt (ähnlich wie die CLR verhindert, dass eine Instanz eines Schnittstellentyp aus aufgebaut wird) konstruiert werden.

Ändern Typ t = def.MakeGenericType (neuer Typ [] {typeof (String), typeof (Objekt)});
auf der
Type t = def.MakeGenericType (new Type [] {typeof (TSource), typeof (String), typeof (Objekt)});

Verwandte Themen