在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
编译器要求使用C#示例中不需要的强制转换Task.FromResult(0) :> Task
。从F#中的ExecuteAsync
方法返回的正确和惯用方法是什么?
答案 0 :(得分:4)
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
但这更浪费。