2016-08-02 13 views
5

関数を基本的にデリゲートとして返すように関数を定義することはできますか?関数などを返す関数を返す関数

public class Scrub 
{ 
    public NotNull NotNull<T>(T value, string name) 
    { 
     if (value == null) throw new ArgumentNullException(name); 
     return NotNull; 
    } 
} 

それから私はチェーンの方法は次のように一緒に呼び出すことができます:これは有効な構文であれば例えば

、。

Scrub.NotNull(param1, nameof(param1))(param2, nameof(param2)(param3, nameof(param3)); 

答えて

14

はまあ、はい、あなたはは、独自のデリゲートの宣言をすることができます

delegate SelfReturner<T> SelfReturner<T>(T value, string name); 

static SelfReturner<T> NotNull<T>(T value, string name) 
{ 
    if (value == null) throw new ArgumentNullException(name); 
    return NotNull; 
} 

...しかし、それは私には便利なようではありません。あなたは本当にこれをやりたがっている理由は何ですか?たとえば、null以外の値を返すPreconditions.CheckNotNullがあります。正直言って、これよりもはるかに便利です。

コメントに記載されているとおり、すべてのパラメータが同じ型(またはすべて最初のパラメータの型に暗黙的に変換可能)である場合にのみ、上記は機能します。

public sealed class NullChecker 
{ 
    public static NullChecker Instance { get; } = new NullChecker(); 
    private NullChecker() {} 

    public static NullChecker Scrub<T>(T value, string paramName) where T : class 
    { 
     if (value == null) 
     { 
      throw new ArgumentNullException(paramName); 
     } 
     return this; 
    } 
} 

として使用する:2つの別個の方法つの静的及び一つと

NullChecker.Instance.Scrub(param1, nameof(param1)) 
        .Scrub(param2, nameof(param2)) 
        .Scrub(param3, nameof(param3)); 

ビットとより多くの仕事は、一般的な方法でシングルトンインスタンスを使用することであろう連鎖を可能にする代替そうではない(ただし名前が異なる)場合は、Instance部分を削除することができます。あなたはそれが拡張メソッド作る場合

NullChecker.Scrub(param1, nameof(param1)) 
      .And(param2, nameof(param2)) 
      .And(param3, nameof(param3)); 
+0

しかし、 'param1'が文字列だった場合、これは' param2'、 'param3'、...も文字列だった場合にのみ有効です。 –

+0

実際には何よりも可能なのかどうか、私は本当に興味がありました。 – adam0101

+1

@IanMercer:ああ、そうです。私はそれを修正するのは簡単ではないと思う - おそらく単なるシングルトンの方法を持っている方が良いでしょう。それを示すために編集します。 –

1

:たとえば

public static class Scrub 
{ 
    public static T NotNull<T, U>(this T value, U property, string name) 
    { 
     if (property == null) throw new ArgumentNullException(name); 
     return value; 
    } 
} 

あなたは行うことができます。

test.NotNull(test.A, nameof(testA.A).NotNull(test.B, nameof(testA.B))); 

ないあなたが何を望むか、かなりの。