Delegates as Adapters C# : More covariance

Dimitris Papadimitriou
1 min readJun 25, 2022

--

this is an extension of the previous post , C# Covarinace and what has to do with Functional C#.

We saw how to to create an adapter to force covarinace in our types. I will demonstrate an alternative way to write the exact same code, by using delegates. The purpose of this is twofold. 1) just deepen the understunding of delegates 2) just style points.

We can all togeather replace the two types

   public interface IFuncTask<out T>
{
T GetResult();
}
public class FuncTaskAdapter<T> : IFuncTask<T>
{
public FuncTaskAdapter(Func<Task<T>> funcTask) =>
this.funcTask = funcTask;
public T GetResult() => funcTask().Result;

}

with a single delegate

public delegate T FuncTask<out T>();

this is essentially the signaure of the T GetResult() method of the interface, this makes sense because a c# delegate is equivalent with a interface with a single method.

we can now create an extension method to convert from Func<Task<T>> to this delegate


static FuncTask<T> ToFuncTask<T>(this Func<Task<T>> @this) =>
new FuncTask<T>(
()=>@this().GetAwaiter().GetResult()
);

and then we can chain stuff on the delegate as usual eg:

static T GetOrThrowIfNull<T>(this FuncTask<T> @this, string message)
{
var value = @this(); // this might also throw exception from Task.
return value ?? throw new Exception(message);
}

we can now write using covarinace

Func<Task<SomeResult>> GetSomethingLazyAsync() => () => Task.FromResult(new SomeResult());


//ok this is covariant on T
FuncTask<IWithResult> lazyResult = GetSomethingLazyAsync().ToFuncTask();

SomeResult result = GetSomethingLazyAsync()
.ToFuncTask()
.GetOrThrowIfNull("failed to get");

the source

https://gist.github.com/dimitris-papadimitriou-chr/9cd3403d42ce1ef6da593d0be5fc0cdc

Unlisted

--

--