2017-07-21 1 views
3

Einige Funktionen meines F # -Codes empfangen Werte als Objekt, obwohl die zugrunde liegenden Werte typisiert sind. Wenn der Wert eine diskriminierte Vereinigung ist, ist es nicht möglich, ihn auf seinen F # -Typ zurückzusetzen. Hier ist ein einfaches Beispiel:Unboxing-Werte von diskriminierten F # -Anschlüssen

type Result<'TOk,'TError> = 
| Ok of 'TOk 
| Error of 'TError 

type ResultA = Result<string, int> 

let a = Ok "A" 
let o = box a 

match o with 
| :? ResultA -> printfn "match ResultA" 
// | :? ResultA.Ok -> printfn "match" // doesn't compile 
| _ when o.GetType().DeclaringType = typedefof<ResultA> -> printfn "match via reflection" 
| _ -> printfn "no match" 

Die Ausgabe von diesem Beispiel ist „Spiel über Reflexion“ wird Resulta nie erreicht, weil der boxed Wert eines anderen CLR-Typs ist - Result.Ok. Da F # diskriminierte Vereinigungsfälle als eigene Typen dargestellt werden, stimmt der eingerahmte Wert nicht mit dem Typ ResultA überein. Darüber hinaus ist es nicht möglich, es mit ResultA.OK abzugleichen, da es sich innerhalb von F # -Code nicht um einen legalen Typ handelt. Die einzige Möglichkeit scheint die manuelle Instanziierung eines Wertes mit Reflektion zu sein, was ineffizient und albern ist, da der Wert bereits instanziiert ist, er ist hier, er kann nur nicht in F # -Code zugegriffen werden, wenn er einmal eingerahmt ist.

Habe ich etwas übersehen? Gibt es eine einfachere Möglichkeit, einen F # diskriminierten Union-Wert aufzuheben?

Antwort

4

Sie passen nur auf einen anderen Typ. Ihre Variable a ist nicht vom Typ ResultA, aber von generischem Typ Result<string, 'a>, die wenn boxed wird gezwungen, Result<string, obj>.

Entweder die Variable machen, die richtige Art ausdrücklich:

let a : ResultA = Ok "A" 

Oder Spiel mit der richtigen Art:

match o with 
| :? Result<string, obj> -> printfn "match ResultA" 

Beide Optionen funktionieren.


Ein Hinweis auf Ihrer Annahme:

Resulta nie, weil der boxed Wert angepasst einem anderen CLR-Typ ist - Result.Ok

, das nicht der Grund. Die Übereinstimmung mit einem Typ funktioniert genauso wie die is/as-Operatoren in C# - d. H., Sie entspricht genau den Subtypen und dem genauen Typ. Und DU-Mitglieder werden als Subtypen des DU-Typs selbst kompiliert. So kann F # .NET dazu bringen, verschiedene Fälle als einen Typ zu behandeln.

Ein Hinweis zur Laufzeit der Eingabe im Allgemeinen:
Handhabung Typen zur Laufzeit sollten nicht notwendig sein. Versuchen Sie es möglichst zu vermeiden. Die Faustregel sollte lauten, wenn Sie sich zur Laufzeit mit Handlingtypen beschäftigen, haben Sie wahrscheinlich etwas falsch modelliert.

Dies gilt insbesondere, wenn Sie nicht wissen genau wie alles funktioniert.

+0

Danke Fjodor. Tatsächlich funktionierte der erste Vorschlag nicht - die Variable zum richtigen Typ zu machen, führte explizit zum selben Boxentyp und stimmte nicht überein. Aber der zweite funktionierte - Ändern des Mustervergleichsfalles. –

+0

Sie müssen einen Fehler gemacht haben, als Sie die erste Option ausprobiert haben. Es funktioniert. –

+0

Und ich stimme Ihrer Vorsorge voll zu. Leider muss ich mich aufgrund der Besonderheiten der externen Bibliothek mit einigen Boxed-Werten auseinandersetzen. –

Verwandte Themen