2017-09-08 2 views
0

Ich versuche, die Fehler zu verwenden, die F # standardmäßig hat: die Ausnahmen.Zurückgeben einer Ausnahme mit dem Ergebnistyp

Ich möchte die Fehler mit dem Ergebnistyp behandeln, aber wenn ich versuche, eine Spezialisierung von Exception, wie ArgumentException, als Fehler zurückzugeben, sagt Visual Studio "diese Funktion nimmt zu viele Argumente oder wird in einem Kontext verwendet, wo eine Funktion wird nicht erwartet ".

Meine Quelle:

let division (x: float) (y: float): Result<float, Exception> = 
    if x = 0.0 then 
     Error (ArgumentException()) 
    else 
     Ok (x/y) 
+2

Ihr Code ist nicht konsistent. Die Argumente sind "x" und "y", aber Sie teilen "a" und "b". Sie prüfen auf 'x' auf Null, ist das dann der Nenner? –

Antwort

3

Das Problem mit Ihrem Code ist, dass der Typ der neu erstellten ArgumentException ist nicht das gleiche wie der Exception Typ, den Sie in der Typ-Signatur angegeben.

Sie können ArgumentException-Exception sicher den :> Operator werfen, aber Fis die Besetzung nicht automatisch einfügen, so dass Sie es selbst schreiben:

let division (x: float) (y: float): Result<float, Exception> = 
    if x = 0.0 then 
     Error (ArgumentException() :> Exception) 
    else 
     Ok (x/y) 

In der Tat kann Fis sogar den Zieltyp schließen von der Typanmerkung, so können Sie schreiben einfach:

Error (ArgumentException() :> _) 

PS: ich sehe, dass du du bist immer „die Funktion nimmt zu viele Argumente“ Fehler sagen. Das ist ziemlich seltsam und vielleicht ist in Ihrem Fall etwas anderes los. Der Fehler, den ich erhalte, wenn ich den Code ausprobiere, lautet: "Dieser Ausdruck hatte den Typ Exception, aber war ArgumentException". Vielleicht definieren Sie auch einige der Standardtypen neu ...

+0

Die Nachricht "Die Funktion benötigt zu viele Argumente" bezieht sich auf eine frühere Version des OP-Codes, in der die Konstruktion des Fehlerfalls wie "FehlerargumentException" aussieht. Anscheinend hat der OP den Code geändert, aber den Fragetext nicht geändert. –

3

Sie Typen und Werte gemischt (Update: diese Antwort bezieht sich vor allem auf die erste Version Ihres Beitrags, TomasP Antwort ist besser für den aktualisierten Code)

  • In der Methodensignatur ist Exception das Typargument zum generischen Typ Result.
  • Im Methodenkörper müssen Sie beim Erstellen des Rückgabewerts Error mit einer Instanz vom Typ Exception aufrufen.

Sie tatsächlich benötigen, um die Operation aufzurufen, werfen konnte (x/y in der Regel nicht, wie in den Kommentaren darauf hingewiesen), die Ausnahme abfangen und dann die Rückkehr:

let division (x: float) (y: float): Result<float, Exception> = 
    try 
     let result = SomethingThatCouldThrow x y 
     Ok result 
    with 
    | e -> Error e 

Btw, ich tun verstehe dein Ziel nicht, "die Fehler zu verwenden, die F # standardmäßig hat: die Ausnahmen." Die .Net-Standardbehandlung einer Fehlerbedingung ist eine Ausnahme, ja. Aber was Sie hier zurückgeben, ist eine Klasse, die die Ausnahme umschließt (im Fehlerfall).

+0

Ich verstehe, Sie wollen sagen, aber ich möchte keine Ausnahmen werfen oder überprüfen, ich möchte nur eine Ausnahme innerhalb der Ergebnisart (anstelle einer "enum") umbrechen. F # hat nicht das Schlüsselwort "new", daher sollte ich die Parenthese für die Objekterstellung verwenden (Ich habe meinen Beitrag bearbeitet). Das Problem ist, dass ich eine Spezialisierung von Exception, wie beispielsweise ArgumentException, nicht zurückgeben kann. –

+0

Mit F # können Sie tatsächlich eine neue Instanz eines Objekts mit dem Schlüsselwort 'new' erstellen. Ich war in der Lage, eine Instanz mit 'let e = new System.ArgumentException (" y ")' zu erstellen (vorausgesetzt, Sie wollen präventiv nach Division durch Null prüfen). –

+0

@Eric Wenn ich versuche, "Error e" zurückzugeben, ist das Problem das gleiche: "Dieser Ausdruck hatte den Typ 'Exception', aber hier ist der Typ 'ArgumentException'". –

Verwandte Themen