Domanda

Ho un pezzo di codice in cui ho bisogno di capire se un determinato tipo implementa IEnumerable<T> (non mi interessa circa il T)

Ho provato (t:System.Type nel caso in cui ti chiedi)

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

, tuttavia, che non verrà compilato (la compilazione non piace il <>). Allora ho provato

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

, ma ottenere un avvertimento che 'un vincolo è a obj. Non voglio per capire se IEnumerable<obj> è implementato, ma IEnumerabl<>.

Uno sa è la soluzione e btw sentitevi liberi di commentare il codice di cui sopra pure.

È stato utile?

Soluzione

Questo dovrebbe funzionare:

typedefof<System.IEnumerable<_>>

Modifica

Come osserva Tomas, non c'è niente di speciale il carattere jolly _ qui; F # deduce che il tipo di obj è il tipo più generale applicabile in questo contesto, quindi questo è lo stesso che utilizza typedefof<System.IEnumerable<obj>>. In alcuni casi il modo in cui funziona può essere un po 'un ostacolo, però. Per esempio, se si definisce un type I<'a when 'a :> I<'a>> = interface end interfaccia, quindi non è possibile utilizzare typedefof<I<_>>, perché I<obj> non soddisfa il vincolo generico e F # non può dedurre un altro tipo più appropriato. Questo può accadere anche senza vincoli ricorsivi (ad esempio type I<'a when 'a : struct and 'a :> System.ICloneable> = interface end. Questo è in contrasto con l'approccio C # s ', che funziona perfettamente bene nei casi analoghi.

Per quanto riguarda il codice stesso, penso che ti consigliamo di fare alcune altre modifiche, anche, come garantire che l'interfaccia è generico prima di chiamare GetGenericTypeDefinition. Ecco come mi piacerebbe scrivere la funzione di test:

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

Altri suggerimenti

Per quanto ne so, F # non ha alcun equivalente a typeof(IEnumerable<>) C # 's. Questo perché, si tratta di una sintassi speciale sostenuto esplicitamente da C #. In F #, typeof è una funzione normale e l'argomento di tipo deve essere un tipo completamente specificato. È possibile ottenere una definizione di tipo generico programatically in questo modo:

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

Il problema con la soluzione con IEnumerable<'a> è che il compilatore F # ha ancora bisogno di trovare qualche tipo concreto da utilizzare (come definizione di tipo generico non è un tipo valido). Se il tipo di inferenza deduce che il parametro di tipo non è limitata in alcun modo, utilizza tipo di default, che è obj.

Modifica non sapevo di typedefof<IEnumerable<_>>, che è molto utile! In ogni caso, notare che la sottolineatura non ha alcun significato speciale qui - l'argomento vero e proprio tipo è ancora IEnumerable<obj>, ma la funzione typedefof chiamate GetGenericTypeDefinition dietro la scena

.

Sarei negligente per non sottolineare che questa domanda è uno dei tanti cui risposte si trovano in

Che cosa significa questo sguardo C # codice come in F #?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top