Frage

Ich habe ein Stück Code, wo ich brauche, um herauszufinden, ob eine bestimmte Art implementiert IEnumerable<T> (I über die T do not care)

Ich habe versucht (t:System.Type falls Sie sich wundern)

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

Sie jedoch, dass nicht kompiliert (die Kompilierung nicht wie die <>). Ich habe dann versucht,

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

aber get ist eine Warnung, dass a‘Einschränkung obj. Ich will nicht, um herauszufinden, ob IEnumerable<obj> implementiert ist aber IEnumerabl<>.

Jeder weiß, ist die Lösung und btw fühlen Sie sich frei zu kommentieren den obigen Code als auch.

War es hilfreich?

Lösung

Dies sollte funktionieren:

typedefof<System.IEnumerable<_>>

Bearbeiten

Wie Tomas Noten, gibt es nichts besonderes über die _ Wildcard hier; F # folgert, dass der Typ obj die allgemeinste anwendbar Typ ist in diesem Zusammenhang, so ist dies das gleiche wie mit typedefof<System.IEnumerable<obj>> ist. In einigen Fällen ist die Art und Weise dieser Arbeiten kann ein wenig hinderlich sein, wenn. Zum Beispiel, wenn Sie eine Schnittstelle type I<'a when 'a :> I<'a>> = interface end definieren, dann können Sie nicht typedefof<I<_>> verwenden, da I<obj> nicht die generische Einschränkung und F # nicht erfüllt kann nicht schließen einen anderen geeigneteren Typ. Dies kann auch ohne rekursive Einschränkungen passiert (z type I<'a when 'a : struct and 'a :> System.ICloneable> = interface end. Dies steht im Gegensatz zu C # 's Ansatz, der völlig in Ordnung in den analogen Fällen funktioniert.

In Bezug auf den Code selbst, ich glaube, Sie einige andere Änderungen vornehmen möchten, auch, wie sichergestellt wird, dass die Schnittstelle vor dem Aufruf GetGenericTypeDefinition generisch ist. Hier ist, wie ich die Testfunktion schreiben würde:

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

Andere Tipps

Soweit ich weiß, F # hat keine äquivalent zu C # 's typeof(IEnumerable<>). Dies liegt daran, dies ist eine spezielle Syntax explizit von C # unterstützt. In F # ist typeof eine normale Funktion und die Art Argument Bedürfnisse ein vollständig spezifizierten Typ sein. Sie können programmatisch wie dies eine generische Typdefinition erhalten:

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

Das Problem mit Ihrer Lösung mit IEnumerable<'a> ist, dass die F # -Compiler muss noch etwas konkreter zu Verwendung finden (als generische Typdefinition kein gültiger Typ ist). Wenn die Typinferenz folgert, dass die Typ-Parameter nicht in irgendeiner Weise eingeschränkt wird, verwendet es Standardtyp, der obj ist.

Bearbeiten ich nicht über typedefof<IEnumerable<_>> wusste, das ist sehr nützlich! Wie dem auch sei, zur Kenntnis, dass der Unterstrich hier keine besondere Bedeutung hat -. Die eigentliche Typargument noch IEnumerable<obj> ist, aber die typedefof Funktionsaufrufe GetGenericTypeDefinition hinter der Szene

Ich wäre nachlässig, nicht darauf zu hinweisen, dass diese Frage ist eine von vielen, deren Antworten finden sich in

Was hier wie ein C # -Code sieht in F #?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top