使用C#中声明的虚拟异步任务,并在F#中重写它



目前我有一段用C#编写的代码,它正被一段F#代码消耗,这两段代码都是.NET库。问题是:

假设我在C#库中有以下类:

namespace Jaxrtech.Logic
{
public class Initializer
{
public Initializer()
{
}
public async Task Setup()
{
// Run implementation independed setup here
// Now call the implementation specific override
await OnSetup();
// Do any additional setup after the implemntation specific stuff
}
// Allow for custom setup tasks to be ran by the Initializer
protected virtual async Task OnSetup()
{
// Return a completed task by default
await Task.FromResult(0);
}
}
}

然后在F#中被覆盖,如下所示:

open System.Threading.Tasks
open Jaxrtech.Logic
type CustomInitializer() =
inherit Initializer()
...
override this.OnSetup(): Task = async {
// custom async logic here
// ex:
do! updateTables()
do! validateData()
}
(* Error: This expression was expected to have type
Task
but here has type
Async<'a>' *)

问题是this.OnSetup()成员正试图返回Async<unit>,但C#库期望一个正常的空Task。我试着浏览了MSDNControl.Async文档,但没有找到任何有用的东西。Async.StartAsTask仍然返回一个类型化的任务,即Task<'a>。因此,这样的事情似乎并不能解决问题:

override this.OnSetup(): Task =
let f: Async<unit> = async {
// Implementation specific setup code here
}
Async.StartAsTask f

相反,现在你会收到一条类似的错误消息:

This expression was expected to have type  
Task  
but here has type  
Task<'a>'

然后你可能会问我为什么一开始就不使用事件。这样做的主要原因是,由于您将返回async void,因此无法在事件上正确使用await来完成。

最后,幸运的是,我同时控制了C#和F#库。任何合理的方式来覆盖这个protected virtual async Task函数或类似的函数都将非常感激。

假设Task<'a>源自Task,您只需稍微修改最后一个片段

override this.OnSetup(): Task =
let f: Async<unit> = async {
// Implementation specific setup code here
}
upcast Async.StartAsTask f

最新更新