如何捕获特定类型的异常而不将结果传递给 F# 中的调用方?
How do you catch a specific type of exception without passing the results to the caller in F#?
我正在尝试捕获特定异常以获取用于记录的基础消息,但我不想将异常传递回调用方法。我知道如何在 C#、F# 中执行此操作?嗯。
这是针对特定异常类型的 w/o 代码。我只是记录方法中发生的问题
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)
| _ -> ()
我遇到的问题是,当我指定异常类型时,异常会沿着链向上传递到调用方法。第一种方法按原样工作,但它没有收集非常有用的信息。
第二种方法是捕获更多错误细节的方法,但它总是将异常向上传递。
如何对我的第二版代码进行最少的修改(如果可能)以防止将错误传回给调用者?
很确定有一种简单的方法可以解决这个问题,但我不是 100% 在 F#
中如何解决
就像在 C# 中一样,您可以在 with
块中有多个模式。它们将按顺序匹配。使用第一个捕获您想要记录的异常,然后使用捕获所有模式来吞下所有其他异常:
try
...
with
| ?: NullReferenceException as ne -> logger.LogError ...
| _ -> ()
编辑 回应评论。
If ?: is the catch what is _ -> () and why is it needed?
:?
和 _ ->
都是“捕获物”。
在 F# 中,就像在 C# 中一样,一个人可以有多个 catch
块 - 几个用于不同类型的异常,并且可选地,一个包罗万象的块,用于其他块中未明确提及的所有异常类型.
例如,在 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# 版本确实具有更多的灵活性 - 例如你可以在 F#-defined exception types 上使用 when
守卫或深度模式匹配。但想法是一样的:多个捕手,连续测试直到一个匹配。
另外需要注意的是语法:?
并不是异常处理的特殊语法。它是 class 层次结构上模式匹配的语法。例如,您可以在常规函数中使用它:
let isString (o: obj) =
match o with
| :? string -> true
| _ -> false
I would think that rather somewhat of stating a "final" ending action
“rather”和“somewhat”这两个词属于自然语言。另一方面,编程语言结构具有非常具体、严格定义的含义,在任何给定时刻可能符合也可能不符合您的直觉。
特别是,C#/F# 中的 finally
块与“捕获所有其他异常”不同。异常捕获器仅在异常发生时执行,而 finally
块执行 不管 是否发生异常。
当没有异常发生时,finally
块在try
之后正常执行。当确实发生异常时,finally
块在 引发异常之前执行 ,并且至关重要的是,异常飞行在 finally
块执行完毕后继续。只是为了开车回家,再来一次:finally
块 不会停止异常 .
finally
块的想法是允许您清理资源并确保无论是否发生异常都会进行清理。
在 C# 中:
try { Console.WriteLine("Working"); }
finally { Console.WriteLine("Done"); }
在 F# 中:
try
printfn "Working"
finally
printfn "Done"
另一件需要注意的事情是,与 C# 不同,F# 不允许在同一块中同时使用 with
和 finally
,原因很复杂。所以如果你需要两者,你必须将它们嵌套在一起。
在 C# 中:
try { Console.WriteLine("Working"); }
catch (NullReferenceException e) { Console.WriteLine("Null"); }
finally { Console.WriteLine("Cleanup"); }
在 F# 中:
try
try
printfn "Working"
with :? NullReferenceException ->
printfn "Null"
finally
printfn "Done"
有关详细信息,请参阅 the docs。
我正在尝试捕获特定异常以获取用于记录的基础消息,但我不想将异常传递回调用方法。我知道如何在 C#、F# 中执行此操作?嗯。
这是针对特定异常类型的 w/o 代码。我只是记录方法中发生的问题
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)
| _ -> ()
我遇到的问题是,当我指定异常类型时,异常会沿着链向上传递到调用方法。第一种方法按原样工作,但它没有收集非常有用的信息。
第二种方法是捕获更多错误细节的方法,但它总是将异常向上传递。
如何对我的第二版代码进行最少的修改(如果可能)以防止将错误传回给调用者? 很确定有一种简单的方法可以解决这个问题,但我不是 100% 在 F#
中如何解决就像在 C# 中一样,您可以在 with
块中有多个模式。它们将按顺序匹配。使用第一个捕获您想要记录的异常,然后使用捕获所有模式来吞下所有其他异常:
try
...
with
| ?: NullReferenceException as ne -> logger.LogError ...
| _ -> ()
编辑 回应评论。
If ?: is the catch what is _ -> () and why is it needed?
:?
和 _ ->
都是“捕获物”。
在 F# 中,就像在 C# 中一样,一个人可以有多个 catch
块 - 几个用于不同类型的异常,并且可选地,一个包罗万象的块,用于其他块中未明确提及的所有异常类型.
例如,在 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# 版本确实具有更多的灵活性 - 例如你可以在 F#-defined exception types 上使用 when
守卫或深度模式匹配。但想法是一样的:多个捕手,连续测试直到一个匹配。
另外需要注意的是语法:?
并不是异常处理的特殊语法。它是 class 层次结构上模式匹配的语法。例如,您可以在常规函数中使用它:
let isString (o: obj) =
match o with
| :? string -> true
| _ -> false
I would think that rather somewhat of stating a "final" ending action
“rather”和“somewhat”这两个词属于自然语言。另一方面,编程语言结构具有非常具体、严格定义的含义,在任何给定时刻可能符合也可能不符合您的直觉。
特别是,C#/F# 中的 finally
块与“捕获所有其他异常”不同。异常捕获器仅在异常发生时执行,而 finally
块执行 不管 是否发生异常。
当没有异常发生时,finally
块在try
之后正常执行。当确实发生异常时,finally
块在 引发异常之前执行 ,并且至关重要的是,异常飞行在 finally
块执行完毕后继续。只是为了开车回家,再来一次:finally
块 不会停止异常 .
finally
块的想法是允许您清理资源并确保无论是否发生异常都会进行清理。
在 C# 中:
try { Console.WriteLine("Working"); }
finally { Console.WriteLine("Done"); }
在 F# 中:
try
printfn "Working"
finally
printfn "Done"
另一件需要注意的事情是,与 C# 不同,F# 不允许在同一块中同时使用 with
和 finally
,原因很复杂。所以如果你需要两者,你必须将它们嵌套在一起。
在 C# 中:
try { Console.WriteLine("Working"); }
catch (NullReferenceException e) { Console.WriteLine("Null"); }
finally { Console.WriteLine("Cleanup"); }
在 F# 中:
try
try
printfn "Working"
with :? NullReferenceException ->
printfn "Null"
finally
printfn "Done"
有关详细信息,请参阅 the docs。