Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Extension methods "Bind" and "Map" for IResult<T> #192

Open
DrPepperBianco opened this issue Aug 23, 2023 · 0 comments
Open

Add Extension methods "Bind" and "Map" for IResult<T> #192

DrPepperBianco opened this issue Aug 23, 2023 · 0 comments

Comments

@DrPepperBianco
Copy link

DrPepperBianco commented Aug 23, 2023

I tried to change my code from Result<TValue> to IResult<TValue> and realized, that IResult<TValue> doesn’t have a Bind or a Map methods.

I think Bind and Map are very important features, therefore I propose adding those methods as Extensions methods.

I prepared some code changes in a fork of this project (see here: https://github.com/DrPepperBianco/FluentResults/blob/features/extensionmethods_for_interface_types/src/FluentResults/Extensions/ResultExtensions.cs).

What I did is, I added extensions methods for IResult<TValue> and also for IResultBase for the following methods:

  • MapErrors
  • MapSuccesses
  • Bind
  • Map
  • ToResult<TValue>

I copied those methods from the Result class and the Result<TValue> class.

I designed those methods, to return either IResult<TValue> (Task<IResult<TValue>>, ValueTask<IResult<TValue>> resp.) or IResultBase (Task<IResultBase>, ValueTask<IResultBase> resp.).

Whenever a new result is created, the IResult<TValue> is actually a Result<TValue>.

This has the disadvantage, that, if the input result had covariance, the output result loses this covariance. This could be circumvented with Reflection, but I am not sure, if this is a good idea.

Alternatives:

Instead of directly providing extension methods for Map, Bind, etc., we could just provide an extensionsMethod AsResult() like that:

public static Result<TValue> AsResult<TValue>(this IResult<TValue> result) 
{
    if(result is Result<TValue> _result)
    {
        return _result;
    }
    else
    {
        return new Result<TValue>()
            .WithValue(result.ValueOrDefault)
            .WithReasons(result.Reasons):
    }
}

Then you could convert an IResult to a result, before working with it.

This method assumes, that most IResults are actually already Results. That is of course not the case, if the result is covariant. In that case, we create a new result object. I named the method AsResult, because in most cases it doesn't create a new object. But that is of course not true, the better name would be ToResult, but that name is of cource already taken for another functionality.

The advantage is, we have fewer methods to maintain. The disadvantage is, that in the case of actual covariance we have create a new object, while an actual extensions method for MapErrorss for instance, could just return the input object instead.

So what do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant