2011-10-04 43 views
4

我一直在试图找出我怎么能使用在iSynaptic.Commons也许单子的情况下在我的价值猎犬可能抛出一个异常:iSynaptic.Commons和也许单子

例如:

dynamic expando = new Expando(); 
expando.Name = "John Doe"; 

var maybe = Maybe.Defer(()=>(string)expando.NonExistingProperty); 

//In this context I would like the exception which is thrown 
//to result in Maybe<string>.NoValue; 
if(maybe.HasValue) { 
    //Do something 
} 

这可能与执行也许是在那里

回答

2

有几种方法使用iSynaptic.Commons允许异常。我发现的每种方法都需要使用.Catch()扩展方法让monad知道默默捕捉异常。另外,访问属性may.Value时要小心。如果此属性为Maybe.NoValue,则会引发InvalidOperationException。


1)创建一个“OnExceptionNoValue”扩展方法。这将检查Maybe以查看它是否有异常。如果有,则返回NoValue Maybe。否则,原来的Maybe将被退回。

public static class MaybeLocalExtensions 
{ 
    public static Maybe<T> OnExceptionNoValue<T>(this Maybe<T> maybe) 
    { 
     return maybe.Exception != null ? Maybe<T>.NoValue : maybe; 
    } 
} 

// Sample Use Case: 
var maybe = Maybe.Defer(() => (string)expando.NonExistingProperty).Catch() 
    .OnExceptionNoValue(); 

2)创建一个 “BindCatch” 扩展方法。这会改变正常绑定的行为,当存在异常时返回Maybe.NoValue而不是抛出异常。

public static class MaybeLocalExtensions 
{ 
    public static Maybe<TResult> BindCatch<T, TResult>(this Maybe<T> @this, Func<T, Maybe<TResult>> selector) 
    { 
     var self = @this; 

     return new Maybe<TResult>(() => { 
      if (self.Exception != null) 
       return Maybe<TResult>.NoValue; 

      return self.HasValue ? selector(self.Value) : Maybe<TResult>.NoValue; 
     }); 
    } 
} 

// Sample Use Case: 
var maybe = Maybe.Defer(() => (string)expando.NonExistingProperty).Catch() 
    .BindCatch(m => m.ToMaybe()); 

3)通过这种方式还使用捕捉()扩展方法,但使用而不是依赖于扩展方法的maybe.HasValue属性。如果Maybe中存在异常,则HasValue属性为false。当这个值为false时,Maybe.NoValue可以替换变量的值,或者在这种情况下需要做的任何事情。

dynamic expando = new ExpandoObject(); 
expando.Name = "John Doe"; 

// This example falls to the else block. 
var maybe = Maybe.Defer(() => (string)expando.NonExistingProperty).Catch(); 

//In this context I would like the exception which is thrown 
//to result in Maybe<string>.NoValue; 
if (maybe.HasValue) { 
    //Do something 
    Console.WriteLine(maybe.Value); 
} else { 
    maybe = Maybe<string>.NoValue; // This line is run 
} 

// This example uses the if block. 
maybe = Maybe.Defer(() => (string)expando.Name).Catch(); 
//to result in Maybe<string>.NoValue; 
if (maybe.HasValue) { 
    //Do something 
    Console.WriteLine(maybe.Value); //This line is run 
} else { 
    maybe = Maybe<string>.NoValue; 
} 

这些答案都在同一主题的所有变化,但我希望他们是有益的。

+0

非常感谢。我知道这一定是可能的,我很喜欢使用Maybe Monad来摆脱空检查的想法。 – Damian

+0

Monads既强大又富有表现力。 Mike Hadlow从一个.Net视角[这里](http://mikehadlow.blogspot.com/2011/01/monads-in-c1-introduction.html)有一篇关于他们的博客系列,帮助我了解基础知识。 – jhamm