2010-09-22 8 views
11

Tengo un tipo genérico:¿Por qué este código se quejaría acerca de "la ariadidad de la definición de tipo genérico"?

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

Y un método de fábrica que (debe) crear una instancia de esta clase para un tipo de diccionario dado.

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

Eliminando todas las cosas extrañas - incluso este código arroja la misma excepción.

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

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

    return Activator.CreateInstance(t); 
} 

El paso Afirma así que sé que T es genérico y tiene dos argumentos genéricos. La línea con MakeGenericType sin embargo exceptúa con:

La cantidad de argumentos genéricos proporcionados no es igual a la ariadidad de la definición de tipo genérico.

Nombre de parámetro: ejemplificación

he hecho este tipo de cosas en el pasado y por la vida de mí, no puede entender por qué esto no está funcionando en este caso. (Además tuve que Google arity).

+0

¿Qué está pasando como 'T' a' CreateDictionaryComparer'? He intentado pasar 'CreateDictionaryComparer >()' y esto funciona bien para mí (usando el compilador de Mono C# versión 1.9.1.0). –

+0

Tenía DictionaryComparer como una clase interna a una que es en sí misma genérica. Creo que fue manguera las obras. – dkackman

+0

Solo por curiosidad, ¿podría proporcionar la muestra completa (fallida) para poder probarla en mi compilador? –

Respuesta

13

Lo descubrí.

Tuve DictionaryComparer declarado como una clase interna. Solo puedo suponer que MakeGenericType quería hacer un Query<T>.DictionaryComparer<string,object> y no se proporcionó T.

A falta de código

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

Solo por curiosidad, ¿podría proporcionar la muestra completa (fallida) para que pueda probarla en mi compilador? –

+0

Déjame ver si puedo quitar cosas no relacionadas a un ejemplo compilable – dkackman

+0

¡Gracias! Mover 'DictionaryComparer ' fuera de la clase de contenedor genérica 'Query ' soluciona el problema. Experimenté y puedes anidar 'DictionaryComparer ', pero no dentro de otra clase genérica. También quería asegurarme de que mi compilador y el entorno de ejecución se comportaran de la misma manera que el suyo. –

1

CLR crea una estructura de datos interna para todos y cada tipo en uso por un estructuras de datos application.These son llamados objetos de tipo. Un tipo con parámetros de tipo genérico se denomina tipo abierto y el CLR no permite que se construya ninguna instancia de un tipo abierto (similar a cómo el CLR impide que se construya una instancia de un tipo de interfaz).

Cambiar Tipo t = def.MakeGenericType (nuevo Tipo [] {typeof (String), typeof (object)});
en la
Tipo t = def.MakeGenericType (nuevo tipo [] {typeof (TSource), typeof (String), typeof (objeto)});

Cuestiones relacionadas