2013-12-06 6 views
2

я принимал участие в реактивных курсах программирования Coursera и заметил параллель междуЕсть ли .NET-эквивалент Scala's Try?

  1. .NET Задачами и Scala Futures
  2. Наблюдаемых, очевидно, очень похожи
  3. .NET IEnumerable и Scala Iterable

в ходе Эрик Мейер рисует таблицу, подобную этой

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

Хотя остальные имеют эквивалентные или подобные конструкции в .NET, я не мог найти ничего подобного try. Существует ли что-то подобное?

+0

Из этого определения: 'Тип Try представляет собой вычисление, которое может либо привести к исключению или возвращать успешно вычисленный value' я не знаю ни одного языковой конструкции, которая непосредственно сопоставляется с этим. «Задача» могла бы обеспечить аналогичный результат: http://msdn.microsoft.com/en-us/library/system.threading.tasks.task(v=vs.110).aspx – asawyer

+1

@asawyer I подумал, что это может быть так. Задача асинхронная, а Try - синхронно, поэтому я не уверен, что она вписывается в ту же позицию в таблице ... :) –

+0

Нет ничего встроенного, поэтому вам придется писать свои собственные. – Lee

ответ

1

Это что-то вроде этого?

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); 
    } 
} 

Вы бы, очевидно, придется перегружать Invoke принять ряд типизированных делегатов, которые вы хотите.

4

Ничего не создано, поэтому вам придется писать свои собственные. На основе Scala Try я хотел бы сделать что-то вроде:

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))); 
    } 
} 
Смежные вопросы