在 F# 中实现 IExceptionHandler 或 IExceptionLogger 等消息处理程序时,返回“空任务”的正确方法是什么?

2024-03-11

在 C# 中,当实现这些处理程序时,我会做类似的事情,

public class DefaultExceptionHandler : IExceptionHandler
{
    public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
    {
        context.Result = new ErrorActionResult(context.Request, context.Exception);

        return Task.FromResult(0);
    }
}

在 F# 中实现相同的接口时,我执行了以下操作:

type DefaultExceptionHandler() =

    let mapExceptionTypetoHttpStatusCode (ex:Exception) : HttpStatusCode =
        match ex with
        | :? ArgumentException -> HttpStatusCode.BadRequest
        | _ -> HttpStatusCode.InternalServerError

    interface IExceptionHandler with
        member x.HandleAsync (context:ExceptionHandlerContext, cancellationToken:CancellationToken) =
            let request = context.Request
            let ex = context.Exception
            let httpStatusCode = mapExceptionTypetoHttpStatusCode ex

            context.Result <- { new IHttpActionResult with member x.ExecuteAsync(token:CancellationToken) = Task.FromResult(request.CreateErrorResponse(httpStatusCode, ex)) }
            Task.FromResult(0) :> Task

编译器需要强制转换Task.FromResult(0) :> Task这在 C# 示例中不是必需的。从返回的正确且惯用的方式是什么ExecuteAsyncF# 中的方法?


F# 编译器需要强制转换,因为在 F# 中没有自动转换为超类型(或任何其他类型)。这是 F# 的一个非常有用的功能,它可以防止一整类错误,其中转换为超类型会改变程序的含义。

所以在你的程序中使用这个强制转换操作符是完全没问题的。如果您不想输入太多内容,您还可以要求编译器为您推断类型:

let a: obj = "abcd"          // No cast - compile-time error
let b: obj = "abcd" :> obj   // Explicit cast to supertype
let c: obj = "abcd" :> _     // Explicit cast to inferred supertype

如果您确实想取消强制转换,则可以使用返回一个任务创建方法Task立即,而不是Task<T>,这需要进行转换。一种这样的方法是Task.Run( Action ):

let t = Task.Run( fun() -> () )   // t: Task

但这样就更加浪费了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 F# 中实现 IExceptionHandler 或 IExceptionLogger 等消息处理程序时,返回“空任务”的正确方法是什么? 的相关文章

随机推荐