iSynaptic.Commons和Maybe Monad

时间:2011-10-04 21:17:19

标签: c# .net monads maybe

我一直试图弄清楚如何在我的值检索器可能抛出异常的上下文中使用iSynaptic.Commons中的Maybe monad:

例如:

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
}

这是否可能实现可能就是那里

1 个答案:

答案 0 :(得分:2)

有几种方法可以使用iSynaptic.Commons来允许异常。我找到的每种方式都需要.Catch()扩展方法让monad知道以静默方式捕获异常。此外,访问该属性时要小心。值。如果此属性为Maybe.NoValue,则将抛出InvalidOperationException。


1)创建一个&#34; OnExceptionNoValue&#34;扩展方法。这将检查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)创建一个&#34; BindCatch&#34;扩展方法。当存在异常以返回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)这种方式也使用Catch()扩展方法,但使用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;
}

这些答案都是同一主题的变体,但我希望它们有所帮助。