2010-03-19 9 views
33

tengo una pieza de código donde tengo que averiguar si un determinado tipo implementa IEnumerable<T> (no me importa acerca de la T)F # equivalente de la C# typeof (IEnumerable <>)

he intentado (t:System.Type en caso de que se preguntan)

let interfaces = t.GetInterfaces() 
let enumerbale = 
    interfaces.Any(fun t -> 
     t.GetGenericTypeDefinition() = typeof<IEnumerable<>> 
    ) 

sin embargo, que no se compilará (la compilación no le gusta la <>). Luego intenté

let interfaces = t.GetInterfaces() 
let enumerbale = 
    interfaces.Any(fun t -> 
     t.GetGenericTypeDefinition() = typeof<IEnumerable<'a>> 
    ) 

pero aparece una advertencia de que 'a es una restricción obj. No quiero averiguar si se implementó IEnumerable<obj> pero IEnumerabl<>.

Cualquiera sabe la solución y por cierto no dude en comentar el código anterior también.

+0

http://stackoverflow.com/questions/1652050/generic-type-definition- syntax-on-f –

Respuesta

49

Esto debería funcionar:

typedefof<System.IEnumerable<_>> 

EDITAR

Como señala Tomás, no hay nada de especial en el comodín _ aquí; F # infiere que el tipo obj es el tipo aplicable más general en este contexto, por lo que esto es lo mismo que usar typedefof<System.IEnumerable<obj>>. En algunos casos, la forma en que esto funciona puede ser un poco un obstáculo, sin embargo. Por ejemplo, si define una interfaz type I<'a when 'a :> I<'a>> = interface end, entonces no puede usar typedefof<I<_>>, porque I<obj> no satisface la restricción genérica y F # no puede inferir otro tipo más apropiado. Esto puede suceder incluso sin restricciones recursivas (por ejemplo, type I<'a when 'a : struct and 'a :> System.ICloneable> = interface end. Esto contrasta con el enfoque de C#, que funciona perfectamente bien en los casos análogos.

En cuanto al código en sí, creo que querrá hacer algunos otros cambios, . también, tales como asegurar que la interfaz es genérico antes de llamar GetGenericTypeDefinition Así es como me gustaría escribir la función de prueba:.

(fun t -> t.IsGenericType && (t.GetGenericTypeDefinition() = typedefof<_ seq>)) 
+0

Su solución me salvó de otro problema :) con un mensaje de error no tan útil "no compatible debido al estado actual del objeto" que es una forma de decir que no puede llamar a getgenerictypedefinition ón un tipo no genérico –

17

Por lo que yo sé, F # no tiene ningún equivalente a C# 's typeof(IEnumerable<>) Este es porque, esta es una sintaxis especial soportada explícitamente por C#. En F #, typeof es una función normal y el argumento de tipo debe ser un tipo completamente especificado. Puede obtener ag definición de tipo eneric programáticamente como esto:

let t = typeof<IEnumerable<obj>> 
let genericT = t.GetGenericTypeDefinition() 

El problema con su solución con IEnumerable<'a> es que el F # compilador todavía tiene que encontrar algún tipo de concreto a utilizar (como tipo de definición genérica no es un tipo válido). Si la inferencia de tipo deduce que el parámetro de tipo no está restringido de ninguna manera, usa el tipo predeterminado, que es obj.

EDIT No sabía acerca de typedefof<IEnumerable<_>>, ¡eso es muy útil! De todos modos, tenga en cuenta que el guión bajo no tiene ningún significado especial aquí - el argumento de tipo real sigue siendo IEnumerable<obj>, pero la función typedefof llama a GetGenericTypeDefinition detrás de la escena.

+0

THanks for la aclaración de la _ –

Cuestiones relacionadas