天天看點

“.NET研究”談談C# 4.0新特性“預設參數”的實作

  C#4.0關于預設參數的新特性,相信大家都不會陌生。所謂預設參數,顧名思義,就是在聲明方法的某個參數的時候為之指定一個預設值,在調用該方法的時候如果采用該預設值,你就無須指定該參數。和很多語言層面特性(文法糖)的實作一樣,預設參數也是編譯器為我們玩的一個小花招。預設參數最終展現為兩個特殊的自定義特性OptionalAttribute和DefaultParameterValueAttribute 。

目錄

一、預設參數的用法

二、實作預設參數的兩個特性:OptionalAttribute和DefaultParameterValueAttribute

三、直接通過OptionalAttribute和DefaultParameterValueAttribute 定義預設參數

  一、預設參數的用法

  比如下面一個TestMethod方法,後面兩個參數bar和baz就是預設參數,預設值分别為“Bar”和“Baz”。

static void TestMethod(string foo, string bar = "Bar", string baz = "Baz")

{

Console.WriteLine("{0, -5} - {1, -5} - {2, -5}", foo, bar, baz);

}

  在調用TestMethod的時候,我們自由地選擇采用預設的參數值,或者覆寫該預設值。

static void Main(string[] args)

TestMethod("Foo");

TestMethod("Foo", "Bar1");

TestMethod("Foo", "Bar1", "Baz1");

}

  下面是輸出結果:

Foo - Bar - Baz

Foo - Bar1 - Baz

Foo - Bar1 - Baz1

  預設參數的使用有兩個簡單的限制,其一是:預設參數的聲明隻能放在普通參數之後。如下代碼中定義的TestMethod方法中,預設參數bar後面跟一個非預設參數baz,這樣的代碼是不能通過編譯的(編譯錯誤資訊為:Optional parameters must appear after all required parameters)。

上海徐彙企業網站設計與制作>

static void TestMethod(string foo, string bar = "Bar", string baz)

}

  但是,預設參數後面可以跟數組參數(params參數),實際上無論在什麼情況下,params參數都隻能是最後一個聲明的參數。關于預設參數的聲明的位置限制,主要重載方法的識别機制決定的,這一點大家都很容易了解。

  預設參數的另一個限制是:指定的預設值必須是一個常量,這就實際上為作為預設參數的資料類型作了限制——隻能是系統定義的基元類型。下面定義的TestMethod方法中,我們定義了一個DateTime類型的預設參數,并将參數預設值作為DateTime.Now。由于DateTime.Now不是常量,是以這樣的代碼也不能通過編譯(編譯錯誤消息:Default parameter value for 'date' must be a compile-time constant)。

static void TestMethod(DateTime date = DateTime.Now)

//Others...

}

  二、實作預設參數的兩個特性:OptionalAttribute和DefaultParameterValueAttribute

  為什麼預設參數的預設值隻能接受常量呢?如果你了解了預設參數的本質,這就不是一個問題。那麼預設參數究竟是如何實作的呢?

  和很多語言層面特性(文法糖)的實作一樣,預設參數也是編譯器為我們玩的一個小花招,而真正編譯後的東西都是我們再熟悉不過的玩意兒。當包含預設參數的C#代碼經過編譯後,預設參數展現在兩個特殊的自定義特性OptionalAttribute和DefaultParameterValueAttribute 。前者将參數辨別為預設參數,後者指定其預設值。

[ComVisible(true), AttributeUsage(AttributeTargets.Parameter, Inherited=false)]

public sealed class OptionalAttribute : Attribute

[AttributeUsage(AttributeTargets.Parameter)]

public sealed class DefaultParameterValueAttribute : Attribute

public DefaultParameterValueAttribute(object value);

public object Value {get; }

  對于最開始我們定義的TestMethod方法,編譯後的形式如下所示。

private static void TestMethod(string foo,

[Optional, DefaultParameterValue("Bar")] string bar,

[Optional, DefaultParameterValue("Baz")] strin上海闵行企業網站設計與制作g baz)

//Others..

  正是因為預設參數的預設值最終是作為DefaultParameterValueAttribute的參數存在的,是以它必須是常量。

  三、直接通過OptionalAttribute和DefaultParameterValueAttribute 定義預設參數

TestMethod("Foo","Bar1");

TestMethod("Foo","Bar1","Baz1");

[Optional, DefaultParameterValue("Baz")] string baz)

private static void Main(string[] args)

TestMethod("Foo", "Bar", "Baz");

TestMethod("Foo", "Bar1", "Baz");

//TestMethod("Foo","Baz");

//上面的方法調用無效

TestMethod("Foo","Bar1","Baz1上海徐彙企業網站制作style='color:white;' href='http://www.93tj.com'>上海網站建設"color: #800000;">");

string baz)

繼續閱讀