2012-02-11 58 views
3

生命是短暫傳遞參數爲多個參數的函數的陣列中的C#

def foo(b,a,r): 
    # bla bla bla 
    pass 

mylist = ['b','a','r'] 
foo(*mylist) 

這就是如何傳遞的參數的列表成方法多個位置參數的Python

但在C#中,我發現使用PARAMS關鍵字傳遞一個數組參數數組的,像這樣的:

void foo(params string[] bar) 
{ 
    // bla bla bla 
} 

string[] mylist = {"b", "a", "r"}; 
foo(mylist) 

試想一下,如果我不能觸摸的功能,是有一種更簡單的方法 有沒有辦法做到這一點?

這裏是我的意思是:

void foo (string b, string a, string r) 
{ 
    // bla bla bla 
} 

string[] mylist = {"b", "a", "r"}; 
foo(mylist[0],mylist[1],mylist[2]); // This line makes my life difficult 

我在網上搜索並不能找到它的替代品。只是想確保我沒有錯過C#提供的隱藏功能。誰知道我們有這樣的捷徑?

+1

如果你不能修改函數參數來接受params數組,那麼你不能這樣做。 – Matthew 2012-02-11 17:25:10

+3

'params'將是解決方案,因此判定C#處於不公平劣勢;-) – BrokenGlass 2012-02-11 17:25:22

+0

但是使用參數參數,我們不知道該方法需要什麼參數以及需要多少參數。這就是爲什麼我用不同的變量名稱分隔每個參數,以便我們知道接下來要傳入的參數是什麼。 – Yeo 2012-02-11 17:54:34

回答

3

沒有,是在C#中沒有的功能,可以讓你直接做這個。但也有一些方法,你可以用它來解決是:

  1. 創建的方法有幾個參數轉換成一個方法與一個陣列參數的方法:

    static Action<T[]> ToArrayMethod<T>(Action<T, T, T> original) 
    { 
        return array => original(array[0], array[1], array[2]); 
    } 
    

    ,然後用它像這樣的:

    string[] array = {"b", "a", "r"}; 
    
    var arrayFoo = ToArrayMethod(foo); 
    
    arrayFoo(array); 
    

    這種方法的缺點是,這種方法僅適用於與一個void返回類型正好三個參數的方法。如果你想讓這個方法適用於有4個參數的方法,或者那些返回一些值的方法,那麼你需要編寫ToArrayMethod()的另一個重載。

  2. 使用反射。如果這樣做,參數傳遞中使用數組:

    var foo = typeof(SomeType) 
        .GetMethod("foo", BindingFlags.Instance | BindingFlags.NonPublic); 
    
    object[] array = {"b", "a", "r"}; 
    
    foo.Invoke(somTypeInstance, array); 
    
+0

感謝您的解決方案, - ) – Yeo 2012-02-11 18:12:41

1

有缺點使用靜態語言,這是其中之一,如果你的函數簽名的定義爲:

void foo (string a, string b, string c); 

那麼你就不得不在3名不同的字符串

foo(mylist[0],mylist[1],mylist[2]); 
傳遞

在C#中具有靈活輸入的唯一方法是使用params您現在已經使用或使用默認值(C#4.0):

void foo (string a, string b = null, string c = null) 

也就是說,如果我沒有通過B或C只是將它們設置爲null,現在你可以調用你的函數是這樣的:

foo(mylist[0]) 
+0

但是使用params string [] bar,我們不知道他們需要什麼參數。這就是爲什麼我用變量分隔每個參數的原因。 – Yeo 2012-02-11 17:48:15

+0

@YeoE準確地說,參數沒有限制,並且在你的情況下不起作用,不幸的是你要麼改變簽名,要麼通過一個錯誤,如果數組長度不完全是3 – 2012-02-11 17:52:42

+0

好吧謝謝:) – Yeo 2012-02-11 17:56:49

0

沒有捷徑。如果你想變得瘋狂,並且你可以稍微修改一下這個函數,那麼你可以重載它以使用params關鍵字簽署一個簽名,並讓原始重載將它的參數傳遞給新的參數。

1

您可以使用反射;但是,通常不建議這樣做,因爲它會犧牲編譯時類型安全性檢查。

下面是一個簡單的方法:

string[] mylist = { "b", "a", "r" }; 
((Action<string,string,string>)foo).DynamicInvoke(mylist); 
+0

感謝您給出的說明...我的意思是類型安全檢查:) – Yeo 2012-02-11 17:43:19

0

所以在這裏總結了很多的答覆,你需要一種對這樣的黑客攻擊,並在我看來,最徹底的方法是沿着這些路線的東西:

爲可枚舉創建擴展功能:

public static class Extensions 
{ 
    public static void SendToMethod<T>(this IEnumerable<T> self, Delegate func ) 
    { 
     Contract.Requires(func.Method.GetParameters().Length == self.Count()); 
     func.DynamicInvoke(self.Cast<object>().ToArray()); 
    } 
} 

然後就可以在陣列發送到任何函數具有的參數數等於所述可枚舉的長度:

public void foo(string a, int b, bool c, string d) {} 
public void foo2(string a, string b, string c) {} 

... 
var test1 = new object[] {"ASDF", 10, false, "QWER"}; 
var test2 = new[] {"A", "B", "C"}; 

test2.SendToMethod((Action<string, string, string>)foo); 
test1.SendToMethod((Action<string, int, bool, string>)foo2); 
+0

個人而言,我不喜歡這個,因爲它是「倒退」。像'method.InvokeWithArray(array)'這樣的東西對我來說更有意義。此外,您可以通過爲每個版本的「動作」重載來避免劇集演員。 – svick 2012-02-11 18:20:44

相關問題