4

私は、値リトリーバーが例外をスローする可能性があるコンテキストで、iSynaptic.CommonsでMaybeモナドをどのように使用できるかを理解しようとしてきました。

例えば:

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
}

これは多分それがそこにある実装で可能ですか?

4

1 に答える 1

2

iSynaptic.Commonsを使用して例外を許可する方法はいくつかあります。私が見つけたそれぞれの方法では、モナドに例外をサイレントにキャッチすることを知らせるために.Catch()拡張メソッドが必要です。また、プロパティmaybe.Valueにアクセスするときは注意してください。このプロパティがMaybe.NoValueの場合、InvalidOperationExceptionがスローされます。


1)「OnExceptionNoValue」拡張メソッドを作成します。これは多分それが例外を持っているかどうか見るために多分をチェックします。含まれている場合は、NoValueが返される可能性があります。それ以外の場合は、元の多分が返されます。

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プロパティを使用します。たぶん例外が存在する場合、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;
}

これらの回答はすべて同じテーマのバリエーションですが、お役に立てば幸いです。

于 2011-10-04T22:05:36.683 に答える