C#4.0新增功能02 命名實參和可選實參

  C# 4 介紹命名實參和可選實參。 經過命名實參,你能夠爲特定形參指定實參,方法是將實參與該形參的名稱關聯,而不是與形參在形參列表中的位置關聯。 經過可選參數,你能夠爲某些形參省略實參。 這兩種技術均可與方法、索引器、構造函數和委託一塊兒使用。html

使用命名參數和可選參數時,將按實參出如今實參列表(而不是形參列表)中的順序計算這些實參。express

命名形參和可選形參一塊兒使用時,你能夠只爲可選形參列表中的少數形參提供實參。 此功能極大地方便了對 COM 接口(例如 Microsoft Office 自動化 API)的調用。編程

命名實參

  有了命名實參,你將再也不須要記住或查找形參在所調用方法的形參列表中的順序。 每一個實參的形參均可按形參名稱進行指定。 例如,經過以函數定義的順序按位置發送實參,能夠採用標準方式調用打印訂單詳細信息(例如賣家姓名、訂單號和產品名稱)的函數。api

PrintOrderDetails("Gift Shop", 31, "Red Mug");ide

若是不記得形參的順序,但卻知道其名稱,則能夠按任意順序發送實參。函數

PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop");ui

PrintOrderDetails(productName: "Red Mug", sellerName: "Gift Shop", orderNum: 31);spa

命名實參還能夠標識每一個實參所表示的含義,從而改進代碼的可讀性。 在下面的示例方法中,sellerName 不得爲 NULL 或空白符。 因爲 sellerName 和 productName 都是字符串類型,因此使用命名實參而不是按位置發送實參是有意義的,能夠區分這兩種類型並減小代碼閱讀者的困惑。excel

當命名實參與位置實參一塊兒使用時,只要code

  • 沒有後接任何位置實參或

PrintOrderDetails("Gift Shop", 31, productName: "Red Mug");

  • 以 C# 7.2 開頭,則它們就有效並用在正確位置 。 在如下示例中,形參 orderNum 位於正確的位置,但未顯式命名。

PrintOrderDetails(sellerName: "Gift Shop", 31, productName: "Red Mug");

可是,若是其後接位置實參,則無序命名實參無效。

// 出現 CS1738 警告: 命名參數規範必須出如今指定了全部固定參數以後。
PrintOrderDetails(productName: "Red Mug", 31, "Gift Shop");

示例

如下代碼執行本節以及某些其餘節中的示例。

class NamedExample
{
    static void Main(string[] args)
    {
        // 使用位置參數以常規方式調用方法。
        PrintOrderDetails("Gift Shop", 31, "Red Mug");

        // 能夠按任意順序爲參數提供命名參數。
        PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop");
        PrintOrderDetails(productName: "Red Mug", sellerName: "Gift Shop", orderNum: 31);

        // 與位置參數混合的命名參數只要在正確的位置使用就有效
        PrintOrderDetails("Gift Shop", 31, productName: "Red Mug");
        PrintOrderDetails(sellerName: "Gift Shop", 31, productName: "Red Mug");    // C# 7.2 onwards
        PrintOrderDetails("Gift Shop", orderNum: 31, "Red Mug");                   // C# 7.2 onwards

        // 可是,若是使用順序不對,則混合參數無效。
        // 下列聲明會引發編譯錯誤
        // PrintOrderDetails(productName: "Red Mug", 31, "Gift Shop");
        // PrintOrderDetails(31, sellerName: "Gift Shop", "Red Mug");
        // PrintOrderDetails(31, "Red Mug", sellerName: "Gift Shop");
    }

    static void PrintOrderDetails(string sellerName, int orderNum, string productName)
    {
        if (string.IsNullOrWhiteSpace(sellerName))
        {
            throw new ArgumentException(message: "Seller name cannot be null or empty.", paramName: nameof(sellerName));
        }

        Console.WriteLine($"Seller: {sellerName}, Order #: {orderNum}, Product: {productName}");
    }
}
可選實參

方法、構造函數、索引器或委託的定義能夠指定其形參爲必需仍是可選。 任何調用都必須爲全部必需的形參提供實參,但能夠爲可選的形參省略實參。

每一個可選形參都有一個默認值做爲其定義的一部分。 若是沒有爲該形參發送實參,則使用默認值。 默認值必須是如下類型的表達式之一:

  • 常量表達式;

  • new ValType() 形式的表達式,其中 ValType 是值類型,例如 enum 或 struct

  • default(ValType) 形式的表達式,其中 ValType 是值類型。

可選參數定義於參數列表的末尾和必需參數以後。 若是調用方爲一系列可選形參中的任意一個形參提供了實參,則它必須爲前面的全部可選形參提供實參。 實參列表中不支持使用逗號分隔的間隔。 例如,在如下代碼中,使用一個必選形參和兩個可選形參定義實例方法 ExampleMethod

public void ExampleMethod(int required, string optionalstr = "default string",int optionalint = 10)

下面對 ExampleMethod 的調用會致使編譯器錯誤,緣由是爲第三個形參而不是爲第二個形參提供了實參。

//anExample.ExampleMethod(3, ,4);

可是,若是知道第三個形參的名稱,則能夠使用命名實參來完成此任務。

anExample.ExampleMethod(3, optionalint: 4);

IntelliSense 使用括號表示可選形參,以下圖所示:

顯示 ExampleMethod 方法的 IntelliSense 快速信息的屏幕截圖。

還可經過使用 .NET OptionalAttribute 類聲明可選參數。 OptionalAttribute 形參不須要默認值。

在如下示例中,ExampleClass 的構造函數具備一個可選形參。 實例方法 ExampleMethod 具備一個必選形參(required)和兩個可選形參(optionalstr 和 optionalint)。 Main 中的代碼演示了可用於調用構造函數和方法的不一樣方式。
 1 namespace OptionalNamespace
 2 {
 3     class OptionalExample
 4     {
 5         static void Main(string[] args)
 6         {
 7             // 實例 anexample 不發送構造函數可選參數的參數。
 8             ExampleClass anExample = new ExampleClass();
 9             anExample.ExampleMethod(1, "One", 1);
10             anExample.ExampleMethod(2, "Two");
11             anExample.ExampleMethod(3);
12 
13             // 實例anoThereExample爲構造函數的可選參數發送參數。
14             ExampleClass anotherExample = new ExampleClass("Provided name");
15             anotherExample.ExampleMethod(1, "One", 1);
16             anotherExample.ExampleMethod(2, "Two");
17             anotherExample.ExampleMethod(3);
18 
19             // 如下語句產生編譯器錯誤。
20 
21             // 必須爲第一個參數提供參數,而且該參數必須是整數。
22             //anExample.ExampleMethod("One", 1);
23             //anExample.ExampleMethod();
24 
25             // 您不能在提供的參數中留下空白。
26             //anExample.ExampleMethod(3, ,4);
27             //anExample.ExampleMethod(3, 4);
28 
29             // 能夠使用命名參數使前一條語句工做。
30             anExample.ExampleMethod(3, optionalint: 4);
31         }
32     }
33 
34     class ExampleClass
35     {
36         private string _name;
37 
38         // 由於構造函數name的參數有一個指定給它的默認值,因此是可選的
39         public ExampleClass(string name = "Default name")
40         {
41             _name = name;
42         }
43 
44         // 第一個參數(必需)沒有指定默認值。所以,它不是可選的。OptionalStr和OptionalInt都有分配給它們的默認值。它們是可選的。
45         public void ExampleMethod(int required, string optionalstr = "default string",
46             int optionalint = 10)
47         {
48             Console.WriteLine("{0}: {1}, {2}, and {3}.", _name, required, optionalstr,
49                 optionalint);
50         }
51     }
52 
53     // 輸出:
54     // Default name: 1, One, and 1.
55     // Default name: 2, Two, and 10.
56     // Default name: 3, default string, and 10.
57     // Provided name: 1, One, and 1.
58     // Provided name: 2, Two, and 10.
59     // Provided name: 3, default string, and 10.
60     // Default name: 3, default string, and 4.
61 
62 }
COM 接口

命名實參和可選實參,以及對動態對象的支持和其餘加強功能大大提升了與 COM API(例如 Office Automation API)的互操做性。

例如,Microsoft Office Excel 的 Range 接口中的 AutoFormat 方法有七個可選形參。 這些形參以下圖所示:

顯示 AutoFormat 方法的 IntelliSense 快速信息的屏幕截圖。

在 C# 3.0 以及早期版本中,每一個形參都須要一個實參,以下例所示。

var excelApp = new Microsoft.Office.Interop.Excel.Application();
excelApp.Workbooks.Add();
excelApp.Visible = true;

var myFormat = Microsoft.Office.Interop.Excel.XlRangeAutoFormat.xlRangeAutoFormatAccounting1;
excelApp.get_Range("A1", "B4").AutoFormat(myFormat, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

可是,能夠經過使用 C# 4.0 中引入的命名實參和可選實參來大大簡化對 AutoFormat 的調用。 若是不但願更改形參的默認值,則能夠經過使用命名實參和可選實參來爲可選形參省略實參。 在下面的調用中,僅爲 7 個形參中的其中一個指定了值。

excelApp.Range["A1", "B4"].AutoFormat( Format: myFormat );

有關詳細信息和示例,請參閱操做說明:在 Office 編程中使用命名參數和可選參數操做說明:使用 Visual C# 功能訪問 Office 互操做對象

重載決策

使用命名實參和可選實參將在如下方面對重載決策產生影響:

  • 若是方法、索引器或構造函數的每一個參數是可選的,或按名稱或位置對應於調用語句中的單個自變量,且該自變量可轉換爲參數的類型,則方法、索引器或構造函數爲執行的候選項。

  • 若是找到多個候選項,則會將用於首選轉換的重載決策規則應用於顯式指定的自變量。 將忽略可選形參已省略的實參。

  • 若是兩個候選項不相上下,則會將沒有可選形參的候選項做爲首選項,對於這些可選形參,已在調用中爲其省略了實參。 這是重載決策中的常規引用的結果,該引用用於參數較少的候選項。

 

相關文章
相關標籤/搜索