2016-08-02 178 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; 
} 

...但它似乎並沒有對我有用。你真的想要這麼做的原因,而不是僅僅做三個獨立的電話?例如,我有一個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; 
    } 
} 

用途爲:

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))); 

你想的不太一樣。