简体   繁体   中英

Is there a .NET equivalent of Scala's Try?

I have been taking part in the Coursera reactive programming course and noticed the parallels between

  1. .NET Tasks and Scala Futures
  2. Observables are obviously very similar
  3. .NET IEnumerable and Scala Iterable

In the course Erik Meijer draws a table similar to this

           Sync     | Async
Single   | Try      | Future
Multiple | Iterable | Observable

While the rest have equivalent or similar constructs in .NET I couldn't find anything like try. Does something similar exist?

There's nothing built in, so you'd have to write your own. Based on the Scala Try I would make something like:

public interface ITry<T> : IEnumerable<T>
{
    T Value { get; }
    ITry<U> SelectMany<U>(Func<T, ITry<U>> bindFunc);
    bool IsSuccess { get; }
}

public class FailedTry<T> : ITry<T>
{
    private readonly Exception ex;
    public FailedTry(Exception ex)
    {
        this.ex = ex;
    }

    public T Value
    {
        get { throw new InvalidOperationException("Can't get value for failed Try"); }
    }

    public ITry<U> SelectMany<U>(Func<T, ITry<U>> bindFunc)
    {
        return new FailedTry<U>(this.ex);
    }

    public bool IsSuccess
    {
        get { return false; }
    }

    public IEnumerator<T> GetEnumerator()
    {
        yield break;
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

public class SuccessTry<T> : ITry<T>
{
    public SuccessTry(T value)
    {
        this.Value = value;
    }

    public T Value { get; private set; }

    public ITry<U> SelectMany<U>(Func<T, ITry<U>> bindFunc)
    {
        if (bindFunc == null) return new FailedTry<U>(new ArgumentNullException("bindFunc"));
        try
        {
            return bindFunc(this.Value);
        }
        catch (Exception ex)
        {
            return new FailedTry<U>(ex);
        }
    }

    public bool IsSuccess
    {
        get { return true; }
    }

    public IEnumerator<T> GetEnumerator()
    {
        yield return this.Value;
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

public static class Try
{
    public static ITry<T> Failed<T>(Exception ex)
    {
        return new FailedTry<T>(ex);
    }

    public static ITry<T> Create<T>(Func<T> create)
    {
        if (create == null) return new FailedTry<T>(new ArgumentNullException("create"));
        try
        {
            return new SuccessTry<T>(create());
        }
        catch (Exception ex)
        {
            return new FailedTry<T>(ex);
        }
    }

    public static ITry<U> Select<T, U>(this ITry<T> @try, Func<T, U> mapFunc)
    {
        return @try.SelectMany(v => Create(() => mapFunc(v)));
    }
}

Is it something like this?

public class Try<TResult>
{
    private readonly bool failure;
    private readonly TResult result;
    private readonly Exception exception;

    protected Try(TResult result)
    {
        this.result = result;
    }

    protected Try(Exception ex)
    {
        this.exception = ex;
        this.failure = true;
    }

    public TResult Result
    {
        get
        {
            if (this.failure) throw new InvalidOperationException();
            return this.result;
        }
    }

    public Exception Exception
    {
        get
        {
            if (!this.failure) throw new InvalidOperationException();
            this.exception;
        }
    }

    public bool Failure
    {
        get
        {
            return this.failure;
        }
    }

    public static Try<TResult> Invoke(Func<TResult> func)
    {
        TResult result;
        try
        {
            result = func();
            return new Try(result);
        }
        catch (Exception ex)
        {
            return new Try(ex);
        }
    }

    public static IEnumerable<Try<TResult>> Invoke(
            IEnumerable<Func<TResult>> funcs)
    {
        return funcs.Select(Invoke);
    }
}

You'd obviously have to overload Invoke to accept the range of typed delegates that you desire.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM