Pregunta

Tengo un pedazo de código en la que tengo que averiguar si un determinado tipo implementa IEnumerable<T> (no me importa el T)

He intentado (t:System.Type en caso que quiera saber)

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 el <>). Luego trató

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

pero llegar es una advertencia de que 'es un obstáculo para el obj. No quiero averiguar si IEnumerable<obj> está implantado, pero IEnumerabl<>.

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

¿Fue útil?

Solución

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 más general aplicable en este contexto, así que esto es lo mismo que usar typedefof<System.IEnumerable<obj>>. En algunos casos, la forma en que esto funciona puede ser un poco de un obstáculo, sin embargo. Por ejemplo, si define un type I<'a when 'a :> I<'a>> = interface end interfaz, entonces usted no puede utilizar typedefof<I<_>>, porque I<obj> no satisface la restricción genérica y F # no se 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 está en contraste con el enfoque de C # 's, que funciona perfectamente bien en los casos análogos.

En cuanto a su propio código, creo que querrá hacer algunos otros cambios, también, como asegurándose de 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>))

Otros consejos

Por lo que yo sé, F # no tiene ningún equivalente a typeof(IEnumerable<>) C # 's. Esto se debe a que, se trata de una sintaxis especial apoyado explícitamente por C #. En F #, typeof es una función normal y el argumento de tipo debe ser un tipo completamente especificado. Usted puede obtener una definición de tipo genérico 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 el tipo de inferencia deduce que el parámetro de tipo no se limita de ninguna manera, se utiliza el tipo predeterminado, que es obj.

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

.

Sería negligente no señalar que esta cuestión es uno de muchos cuyas respuestas se encuentran en

Lo que hace este código C # verá como en F #?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top