vkhorikov / CSharpFunctionalExtensions

Functional extensions for C#

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Maybe extensions for MapTry and ExecuteTry

tinytownsoftware opened this issue · comments

I think these two extensions would be good to have. While I know I can just do a ToResult() and then just MapTry (and TapTry instead of Execute), it would save the ToResult() call and I wouldn't have to leave the Maybe realm if there is no reason to.

I was also thinking of just returning Maybe for MapTry and in the case of an exception it would just be None, but then you lose the context of the exception. But that can easily be solved by providing an Action callback and let the user decide what to do with the exception, if anything.

Here is the basic version (similar for Execute):

public static partial class MaybeExtensions
{
    /// <summary>
    ///     Creates a new Maybe from the return value of a given function. If the calling Maybe is a failure, None is returned instead.
    ///     If the function throws an exception, the error handler is invoked and None is returned.
    /// </summary>
    public static Maybe<K> MapTry<T, K>(this Maybe<T> maybe, Func<T, K> selector, Action<Exception> errorHandler = null)
    {
        if (maybe.HasNoValue)
            return Maybe<K>.None;

        return Maybe<K>.Try(() => selector(maybe.GetValueOrThrow()), errorHandler);
    }
}

public partial struct Maybe<T>
{
    public static Maybe<T> Try(Func<T> func, Action<Exception> errorHandler = null)
    {
        try
        {
            return From(func());
        }
        catch (Exception exc)
        {
            errorHandler?.Invoke(exc);
            return None;
        }
    }
}

If you think it would be a good addition, I can create a PR, I have the changes done and unit tested.

I'm not sure about returning Maybe in cases where an exception is possible. I'd rather stick to Result in such situations.

Makes sense, closing.