2010-08-27 57 views
13

是否有可能擁有可以使用Dynamic-invoke調用的可變數量的參數的C#lambda/delegate?C#中的變量參數Lambda

我在這種情況下使用'params'關鍵字的所有嘗試都失敗了。


有工作碼更新FROM ANSWER

delegate void Foo(params string[] strings); 

static void Main(string[] args)      
{ 
    Foo x = strings => 
    { 
     foreach(string s in strings) 
      Console.WriteLine(s); 
    }; 

    //Added to make it clear how this eventually is used :) 
    Delegate d = x; 

    d.DynamicInvoke(new[]{new string[]{"1", "2", "3"}}); 
} 
+0

你可以發佈代碼,你已經嘗試到目前爲止,讓你更好地瞭解你在找什麼? – 2010-08-27 03:27:00

+0

我認爲他正在嘗試做'Func func' – tster 2010-08-27 03:31:46

回答

15

直接傳遞的參數DynamicInvoke()當它不工作的原因是因爲DynamicInvoke()期望對象的數組,爲一個元件目標方法的每個參數,並且編譯器會將單個數組解釋爲params數組到DynamicInvoke()而不是目標方法的單個參數(除非您將其轉換爲作爲單個object)。通過傳遞一個包含目標方法參數數組的數組,可以調用DynamicInvoke()。外部數組將被接受爲DynamicInvoke()的單個參數params參數的參數,內部數組將被接受爲目標方法的params數組。

delegate void ParamsDelegate(params object[] args); 

static void Main() 
{ 
    ParamsDelegate paramsDelegate = x => Console.WriteLine(x.Length); 

    paramsDelegate(1,2,3); //output: "3" 
    paramsDelegate();  //output: "0" 

    paramsDelegate.DynamicInvoke((object) new object[]{1,2,3}); //output: "3" 
    paramsDelegate.DynamicInvoke((object) new object[]{}); //output: "0" 

    paramsDelegate.DynamicInvoke(new []{new object[]{1,2,3}}); //output: "3" 
    paramsDelegate.DynamicInvoke(new []{new object[]{}});  //output: "0" 
} 
+0

我必須缺少一些東西。在ParamsDelegate上調用DynamicInvoke會有什麼意義?或者你認爲這只是爲了防止你將'ParamsDelegate'鍵入爲'Delegate'? – 2010-08-27 04:05:34

+0

@wb我用解釋更新了答案。 – 2010-08-27 04:34:58

+0

+1沒有'DynamicInvoke'的方法。即使沒有基準測試,DynamicInvoke也是我盡力避免的。這有點太慢了。 – nawfal 2013-12-22 01:50:54

1

不,但它所採取的任何參數都可以是數組。

沒有更多的細節,這是它的長與短。

0

沒有,但有一點幫助,你幾乎可以僞造它:

object[] Params(params object[] args) { return args;} 

// : 

Action<string, object[]> CWL = 
        (format, args) => Console.WriteLine(format, args); 

CWL("{0}, {1}", Params(1,2)); 
+5

男人,一旦微軟推出這些'Action' *和'Func' *代表,就好像每個人都忘記了你實際上也允許聲明自己的代碼... – 2010-08-27 03:57:22

0

添加到馬克的回答,我會創建一個擴展方法來清理了一下:

static DynamicInvokeParams(this ParamsDelegate delegate, params object[] args) 
{ 
    delegate.DynamicInvoke(new [] {args}); 
} 

然後你只需說:

paramsDelegate.DyanamicInvokeParams(1, 2, 3); 
+0

但是你爲什麼要這麼做,只需要編寫'paramsDelegate (1,2,3);'? – 2010-08-27 04:04:24

+0

公平點;我猜想OP可能想要使用DynamicInvoke,因爲它們有一個數組,所以它更可能是'paramsDelegate.DynamicInvokeParams(new [] {1,2,3})',它仍然更好一些。 – 2010-08-27 04:17:06

0

我覺得有一個非常關鍵的一點,這裏沒有討論,那就是如果您定義了一個採用params參數的委託類型,那麼在上調用DynamicInvoke幾乎沒有意義。只有我可以想象這種情況會發生的情況是,如果您有自定義類型的代理,並且您將它作爲參數傳遞給某個接受Delegate參數的方法,並且在上調用DynamicInvoke

但是讓我們看看這段代碼在OP的更新:

delegate void Foo(params string[] strings); 

static void Main(string[] args)      
{ 
    Foo x = strings => 
    { 
     foreach(string s in strings) 
      Console.WriteLine(s); 
    }; 

    x.DynamicInvoke(new[]{new string[]{"1", "2", "3"}}); 
} 

DynamicInvoke撥打以上是完全多餘的。這將是最後一行閱讀更合理:

x("1", "2", "3"); 
+0

是的,在這個簡化的情況下,它是無用的,但在實際的實施情況下,它不會變成一個其他地方調用的總代表。我會更新我的帖子,使其更明顯。 – iam 2010-08-27 04:16:51

+0

@wb:好的,在那種情況下,我可以理解你需要解決這個問題。我會用我認爲會幫助你的解釋來更新我的答案。 – 2010-08-27 04:21:47

+0

我仍然有點不確定爲什麼..新[] {...部分是需要的,但我應該補充。 – iam 2010-08-27 04:23:24