Use a virtual async Task declared in C# and override it in F#

.net, async-await, asynchronous, c#, f#

Solution

Given that `Task<'a>` derives from `Task` you can just slightly modify your last snippet

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

Problem

Currently I have a piece of code written in C# that is being consumed by a piece of F# code both being .NET libraries. Here is the issue: Assume I have the following class in the C# library: ``` 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); } } } ``` And is then overridden in F# as such: ``` 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>' *) ``` The issue is the `this.OnSetup()` member is trying to return `Async<unit>` but the C# library is expecting a normal empty `Task`. I've tried looking through the MSDN `Control.Async` documentation but did not find much of any avail. `Async.StartAsTask` still returns a typed task, i.e. `Task<'a>`. So something like this does not seem to solve the problem: ``` override this.OnSetup(): Task = let f: Async<unit> = async { // Implementation specific setup code here } Async.StartAsTask f ``` Instead now you will be greeted by a similar error message: ``` This expression was expected to have type Task but here has type Task<'a>' ``` You may then ask why I am not using events in the first place. The main reason for that is then since you are going to be returning `async void` there is no way to properly use `await` on the event to complete. Finally, I luckily have control over both the C# and F# libraries. Any reasonable way to override this `protected virtual async Task` function or alike would be greatly appreciated.

Original source