Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 209
Josh Bowden Avatar asked Feb 20 '14 03:02

Josh Bowden


People also ask

What is virtual async?

In asynchronous virtual learning the learner enriches their knowledge at their own tempo at a time convenient for themselves. Learning is not restricted by place and time. The learning process is not dependent on fixed time intervals which serve to regulate the sequence of activities.

What is an async task C#?

An async method runs synchronously until it reaches its first await expression, at which point the method is suspended until the awaited task is complete. In the meantime, control returns to the caller of the method, as the example in the next section shows.

Can I use async in interface?

Interfaces can't use async in a method declaration, simply because there is no need. If an interface requires that a method returns Task , the implementation may choose to use async , but whether it does or not is a choice for the implementing method.


1 Answers

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
like image 154
desco Avatar answered Sep 28 '22 11:09

desco