Skip to content

Instantly share code, notes, and snippets.

@dimitris-papadimitriou-chr
Last active June 25, 2022 17:58
Show Gist options
  • Save dimitris-papadimitriou-chr/578f76c2d4b8d18f6f7fc8e69dcf0153 to your computer and use it in GitHub Desktop.
Save dimitris-papadimitriou-chr/578f76c2d4b8d18f6f7fc8e69dcf0153 to your computer and use it in GitHub Desktop.
C# Covarinace and what has to do with Functional C#
using System;
using System.Threading.Tasks;
namespace FunctionalExperimentation.Practical.FuncTaskCovarinat
{
public static partial class F
{
public static IFuncTask<T> ToWithResult<T>(this Func<Task<T>> @this) => new FuncTaskAdapter<T>(@this);
public static T GetOrThrowIfNull<T>(this IFuncTask<T> @this, string message)
{
var value = @this.GetResult(); // this might also throw exception from Task.
return value ?? throw new Exception(message);
}
public static T GetOrThrow<T>(this IFuncTask<T> @this, string message)
{
try
{
return @this.GetOrThrowIfNull(message);
}
catch (Exception e) //Please Dont hide Exceptions
{
throw new Exception(message);
}
}
}
public interface IWithSuccess
{
public bool IsSuccessful { get; }
}
public class SomeResult : IWithSuccess
{
public bool IsSuccessful => true;
}
public class FuncTaskCovarinat
{
public static async Task RunAsync()
{
Func<Task<SomeResult>> GetSomethingLazyAsync() => () => Task.FromResult(new SomeResult());
//Func<Task<IWithResult>> t = GetSomethingLazyAsync();
//Error CS0029 Cannot implicitly convert type 'System.Func<System.Threading.Tasks.Task<FunctionalExperimentation.Practical.FuncTaskCovarinat.SomeResult>>'
// to 'System.Func<System.Threading.Tasks.Task<FunctionalExperimentation.Practical.FuncTaskCovarinat.IWithResult>>'
//ok this is covariant on T
IFuncTask<IWithSuccess> lazyResult = GetSomethingLazyAsync()
.ToWithResult();
SomeResult result = GetSomethingLazyAsync()
.ToWithResult()
.GetOrThrow("failed to get");
}
public static async Task RunAsyncClassic()
{
Func<Task<SomeResult>> GetSomethingLazyAsync() => () => Task.FromResult(new SomeResult());
SomeResult result;
var lazyTask = GetSomethingLazyAsync();
result = await lazyTask();
if (result is null)
throw new Exception("failed to get Anything");
}
public static async Task RunAsyncClassicExtendedWithTryCatch()
{
Func<Task<SomeResult>> GetSomethingLazyAsync() => () => Task.FromResult(new SomeResult());
SomeResult result;
try
{
var lazyTask = GetSomethingLazyAsync();
result = await lazyTask();
if (result is null)
throw new Exception("failed to get Anything");
}
catch (Exception e) //Please Dont hide Exceptions
{
throw new Exception("failed to get Anything");
}
}
}
public interface IFuncTask<out T>
{
T GetResult();
}
public class FuncTaskAdapter<T> : IFuncTask<T>
{
public Func<Task<T>> Unwrap() => funcTask;
private readonly Func<Task<T>> funcTask;
public FuncTaskAdapter(Func<Task<T>> funcTask) =>
this.funcTask = funcTask;
public T GetResult() => funcTask().Result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment