有几种方法可以使用 iSynaptic.Commons 来允许异常。我发现的每种方式都需要 .Catch() 扩展方法来让 monad 知道静默捕获异常。另外,访问属性maybe.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)这种方式也使用了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;
}
这些答案都是同一主题的变体,但我希望它们有所帮助。