2013年5月29日 星期三

[C#]Optional parameters and Named arguments

C#從4.0版之後開始支援optional parameters以及named arguments,這兩個語法通常會一起使用。他讓我們的程式碼變得更簡潔並增加可讀性。首先先來介紹什麼是Parameters and Arguments。

Parameters and Arguments

Parameters和Arguments是兩個很容易搞混的名詞,先來定義這兩者有什麼不同。下面是一段程式碼範例:

void Foo(int x, int y)
{
// Do something with x and y
}
...
int a = 10;
Foo(a, 20);

parameters是function定義時所使用的變數,arguments是我們呼叫function時傳進去的變數或值 範例中的x和y是parameters,a和20是arguments。

Optional parameters

Optional parameters簡單說就是給parameter一個特定的預設值,當使用者沒有傳入此parameter所對應的arguments時,會自動使用預設值。在C#4.0之前沒有optional parameters,如果要達到這個功能必須使用overloading function,會造成寫一大堆overloading function的情況,並不是很好使用。C#4.0之後使用optional parameters可以免去宣告一堆overloading function的困擾。以下是optional parameters的一個簡單範例:

static void Dump(int x, int y = 20, int z = 30)
{
    Console.WriteLine("x={0} y={1} z={2}", x, y, z);
}
...
Dump(1, 2, 3);
Dump(1, 2);
Dump(1);

我們設定y和z的預設值為20和30,當我們在呼叫function時,編譯器會根據我們提供的參數去做對應,找出最合適的function。程式執行結果如下:

x=1 y=2 z=3
x=1 y=2 z=30
x=1 y=20 z=30

程式會從parameters list的左邊到右邊一一去對應參數。如果出現無法對應的情況會丟出exception。

由於optional parameters和arguments的對應是按照宣告的順序,因此當我們呼叫Dump(1, 2)時會自動把y對應成2,沒辦法把2對應到z讓y使用預設值。要讓參數能自由對應需要使用接下來要介紹的named arguments。

parameter的預設值必須是一個常數,因此以下範例是錯誤的,因為DataTime.Now並不是一個常數。

Foo(DateTime dt = DateTime.Now)

Optional parameters也被限制必須放在後面,不能放在非optional parameters之前。

Foo(int x = 0, int y)

Name Arguments

Name arguments讓我們可以不按照順序傳入參數。他的語法是在argument前加入一個對應parameter的名稱。以下是範例:

static void Dump(int x, int y, int z)
{
    Console.WriteLine("x={0} y={1} z={2}", x, y, z);
}
...
Dump(1, 2, 3);
Dump(x: 1, y: 2, z: 3);
Dump(z: 3, y: 2, x: 1);
Dump(1, y: 2, z: 3);
Dump(1, z: 3, y: 2);

不管argument的順序是如何,編譯器會自動幫我們對應到正確的parameters名稱。

x=1 y=2 z=3
x=1 y=2 z=3
x=1 y=2 z=3
x=1 y=2 z=3
x=1 y=2 z=3

Abusing argument evaluation order

int i = 0;
Dump(z: ++i, x: ++i, y: ++i);
x=2 y=3 z=1

上面這行程式碼輸出的結果可能會和你想的不一樣,這是因為傳進去的argument還是根據他宣告的順序做計算,而不是patameters的順序。我們應該要避免寫出這種程式碼。

1 則留言: