Reputation: 5980
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.
Upvotes: 5
Views: 1969
Reputation: 16782
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
Upvotes: 6