F # Äquivalent der C # typeof (IEnumerable <>)
-
21-09-2019 - |
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.
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