F# 如何在不将结果传递给F中的调用者的情况下捕获特定类型的异常?

F# 如何在不将结果传递给F中的调用者的情况下捕获特定类型的异常?,f#,c#-to-f#,F#,C# To F#,我试图捕获一个特定的异常以获取用于日志记录的底层消息,但我不希望将异常传递回调用方法。我知道怎么用C,F来做这个?嗯 下面是不针对特定异常类型工作的代码。我只是记录方法中发生的问题 match remoteApiResponse.StatusCode with | HttpStatusCode.OK -> let! resp = remoteApiResponse.Content.ReadAsStringAsync() |> A

我试图捕获一个特定的异常以获取用于日志记录的底层消息,但我不希望将异常传递回调用方法。我知道怎么用C,F来做这个?嗯

下面是不针对特定异常类型工作的代码。我只是记录方法中发生的问题

        match remoteApiResponse.StatusCode with
        | HttpStatusCode.OK ->
            let! resp = remoteApiResponse.Content.ReadAsStringAsync() |> Async.AwaitTask
            try
                let IsSuccess = JObject.Parse(resp).["IsSuccess"].ToString().Trim().ToLower()
                match IsSuccess with
                | "true" -> ()
                | "false" -> remoteApiResponse.StatusCode <- HttpStatusCode.BadRequest
                | _ -> ()
            with 
            | _ ->  logger.LogError("Error Occurred during IsSuccess flag validation.") 
        | _ -> ()
在下面的代码中,我的目标是计算NullReferenceException类型,但它实际上可能是任何类型的错误

    match remoteApiResponse.StatusCode with
        | HttpStatusCode.OK ->
            let! resp = remoteApiResponse.Content.ReadAsStringAsync() |> Async.AwaitTask
            try
                let IsSuccess = JObject.Parse(resp).["IsSuccess"].ToString().Trim().ToLower()
                match IsSuccess with
                | "true" -> ()
                | "false" -> remoteApiResponse.StatusCode <- HttpStatusCode.BadRequest
                | _ -> ()
            with 
            | :? NullReferenceException as ne -> logger.LogError("Error Occurred during IsSuccess flag validation." + ne.Message) 
        | _ -> ()
我看到的问题是,当我指定一个异常类型时,异常会沿着链向上传递给调用方法。第一种方法按原样工作,但它没有收集非常有用的信息

第二种方法是捕获更多错误细节的方法,但它总是将异常带到链的上游

如果可能的话,如何对我的第二个版本的代码进行最小程度的修改,以防止错误传回调用方?
非常确定有一种简单的方法可以解决这个问题,但我不知道在F

中如何像在C中一样,在with块中可以有几个模式。它们将按顺序匹配。使用第一个模式捕获要记录的异常,然后使用“捕获所有”模式吞并所有其他异常:

try
  ...
with
| ?: NullReferenceException as ne -> logger.LogError ...
| _ -> ()
根据评论进行编辑

如果?:捕获物是什么?为什么需要它

两者:?和u->是陷阱

在F中,就像在C中一样,一个可以有多个catch块——多个用于不同类型的异常,另一个可选的是,一个catch all块用于其他块中未明确提到的所有异常类型

例如,在C中:

try { throw ... }
catch (NullReferenceException e) { Console.WriteLine("Null"); }
catch (NotImplementedException e) { Console.WriteLine("Not impl"); }
catch (InvalidOperationException e) { Console.WriteLine("Invalid op"); }
catch { Console.WriteLine("No idea what happened"); }
F中的等效代码:

try
  ...
with
| ?: NullReferenceException as e -> printfn "Null"
| ?: NotImplementedException as e -> printfn "Not impl"
| ?: InvalidOperationException as e -> printfn "Invalid op"
| _ -> printfn "No idea what happened"
F版本确实有更大的灵活性-例如,您可以在防护或深度模式匹配时使用。但想法是一样的:多个接球手,连续测试,直到一个接球手比赛

另一个需要注意的是语法:?对于异常处理来说并不特殊。它是类层次结构上模式匹配的语法。例如,您可以在常规函数中使用它:

let isString (o: obj) = 
  match o with 
  | :? string -> true
  | _ -> false
我认为这有点像是在陈述一个最终的结束行动

这些词在某种程度上属于自然语言。另一方面,编程语言结构具有非常具体、严格定义的含义,在任何给定时刻都可能与您的直觉相匹配,也可能不匹配

特别是,C/F中的finally块与捕获所有其他异常不同。虽然异常捕捉器仅在异常发生时执行,但finally块的执行与异常是否发生无关

当没有异常发生时,finally块在try之后正常执行。当异常确实发生时,finally块在引发异常之前执行,并且,至关重要的是,异常飞行在finally块完成执行之后继续。为了让大家明白这一点,再一次:finally块不会停止异常

finally块的思想是允许您清理资源,并确保无论是否发生异常,都会进行清理

在C中:

在F中:

另一件需要注意的事情是,与C不同,F不允许在同一块中同时包含with和finally,原因很复杂。因此,如果你需要两者,你必须将它们相互嵌套

在C中:

在F中:


有关更多信息,请参见。

与在C中一样,with块中可以有多个模式。它们将按顺序匹配。使用第一个模式捕获要记录的异常,然后使用“捕获所有”模式吞并所有其他异常:

try
  ...
with
| ?: NullReferenceException as ne -> logger.LogError ...
| _ -> ()
根据评论进行编辑

如果?:捕获物是什么?为什么需要它

两者:?和u->是陷阱

在F中,就像在C中一样,一个可以有多个catch块——多个用于不同类型的异常,另一个可选的是,一个catch all块用于其他块中未明确提到的所有异常类型

例如,在C中:

try { throw ... }
catch (NullReferenceException e) { Console.WriteLine("Null"); }
catch (NotImplementedException e) { Console.WriteLine("Not impl"); }
catch (InvalidOperationException e) { Console.WriteLine("Invalid op"); }
catch { Console.WriteLine("No idea what happened"); }
F中的等效代码:

try
  ...
with
| ?: NullReferenceException as e -> printfn "Null"
| ?: NotImplementedException as e -> printfn "Not impl"
| ?: InvalidOperationException as e -> printfn "Invalid op"
| _ -> printfn "No idea what happened"
F版本确实有更大的灵活性-例如,您可以在防护或深度模式匹配时使用。但想法是一样的:多个接球手,连续测试,直到一个接球手比赛

另一个需要注意的是语法:?对于异常处理来说并不特殊。它是类层次结构上模式匹配的语法。例如,您可以在常规函数中使用它:

let isString (o: obj) = 
  match o with 
  | :? string -> true
  | _ -> false
我认为这有点像是在陈述一个最终的结束行动

这些词在某种程度上属于自然语言。另一方面,编程语言结构具有非常具体、严格定义的含义,在任何给定时刻都可能与您的直觉相匹配,也可能不匹配

特别是,C/F中的finally块与捕获所有其他异常不同。虽然异常捕捉器仅在异常发生时执行,但无论exc 已经发生了一种误解

当没有异常发生时,finally块在try之后正常执行。当异常确实发生时,finally块在引发异常之前执行,并且,至关重要的是,异常飞行在finally块完成执行之后继续。为了让大家明白这一点,再一次:finally块不会停止异常

finally块的思想是允许您清理资源,并确保无论是否发生异常,都会进行清理

在C中:

在F中:

另一件需要注意的事情是,与C不同,F不允许在同一块中同时包含with和finally,原因很复杂。因此,如果你需要两者,你必须将它们相互嵌套

在C中:

在F中:


有关更多信息,请参阅。

对于其他类型的异常,您希望发生什么情况?除了NullReferenceException之外?对于其他类型的异常,您希望发生什么?除了NullReferenceException?谢谢,我想你回答的最后一行是我需要解决的问题。添加该行可防止错误返回上游。我猜这类似于C try catch finally,但异常获取句柄的方式在C中的F b/C中似乎略有不同。我可以省略finally块,这样就足以不允许异常继续。但是在F中,如果你添加的最后一行丢失,结果似乎是不同的。。。吸取的教训。这个F代码中没有finally块,我不明白。如果?:捕获物是什么?为什么需要它?如果它告诉F忽略所有其他例外,我会认为这相当于说明一个最终的结束动作。我修改了答案。谢谢,我认为你答案的最后一行是我解决问题所需要的。添加该行可防止错误返回上游。我猜这类似于C try catch finally,但异常获取句柄的方式在C中的F b/C中似乎略有不同。我可以省略finally块,这样就足以不允许异常继续。但是在F中,如果你添加的最后一行丢失,结果似乎是不同的。。。吸取的教训。这个F代码中没有finally块,我不明白。如果?:捕获物是什么?为什么需要它?如果它告诉F忽略所有其他例外,我会认为这相当于说明一个最终的结束动作。我修改了答案。