《Effective C#》读书笔记——条目10:使用可选参数减少方法重载的数量<C#语言习惯>
C#4.0 引入了具名参数(MSDN翻译为“命名实参”,个人认为具名参数更形象,可选参数亦是)和可选参数(可选实参)。客户端代码使用具名参数意味着:方法中的参数名称也成为了公有接口的一部分。假如修改公有参数的名称将有可能破坏调用者的代码。这意味着:调用者应该尽可能的避免使用具名参数,而作为API的设计者,也应该避免修改公有货受保护方法中参数的名称。
当然,并不是说具名参数是一无是处的,它也有自己的适用的场景。具名参数配合可选参数可以简化很多API的调用语法,特别是Microsoft Office的COM API。如下:
1 var wasted = Type.Missing; 2 var wordApp = new Microsoft.Office.Interop.Word.Application(); 3 wordApp.Visible = true; 4 5 Documents docs = wordApp.Documents; 6 Document doc = docs.Add(ref wasted, ref wasted, ref wasted); 7 8 Range range = doc.Range(0, 0); 9 range.InsertAfter("Testing,testing,testing...");
任何的Office Interop应用程序都要使用多次Type.Missing对象,这些毫无意义的代码掩盖了核心的逻辑;这是C#添加可选参数和具名参数主要原因。在添加可选参数后在Office API将会为可能使用Type.missing的地方创建默认值,上面的代码可以简化成这样:
1 var wordApp = new Microsoft.Office.Interop.Word.Application(); 2 wordApp.Visible = true; 3 4 Documents docs = wordApp.Documents; 5 Document doc = docs.Add(); 6 7 Range range = doc.Range(0, 0); 8 range.InsertAfter("Testing,testing,testing...");
我们可以看到这个小小的修改增强了代码的可读性。现在假设你想创建一个新的Web页面而不是一个Word文档,而这时Add()方法的最后一个参数,这种情况下可以使用具名参数来指定最后一个参数:
1 var wordApp = new Microsoft.Office.Interop.Word.Application(); 2 wordApp.Visible = true; 3 Documents docs = wordApp.Documents; 4 5 object docType = WdNewDocumentType.wdNewWebPage; 6 Document doc = docs.Add(DocumentType: ref docType); 7 8 Range range = doc.Range(0, 0); 9 range.InsertAfter("Testing,testing,testing...");
具名参数的具体含义是:对于那些提供了默认从参数的API,你可以仅提供要用到的那些参数。使用具名参数要比使用多个重载要简单得多。在上面的实例示例中的第六行的ADD方法具名参数使用了ref关键字,在COM场景的编程中使用C#4.0,ref参数也是可选的:因为COM本身都是通过引用传递对象的,所以几乎所有的参数都会以引用的形式传递,即使这些参数不会被调用的方法修改。
在协作开发中,如果你的代码需要供他人调用,不管你是否同意你的API使用者都可以在任意的地方使用具名参数调用你的方法,所以你必须将参数的名称也当作公有接口的一部分。修改参数名称可能会导致客户代码无法通过编译。
小节:
对于程序集的第一次发布,可以随意使用可选参数和具名参数,并任意给出你想要提供的重载。但是在后续的发布中,必须为额外的参数创建重载。这样才能保证现有的程序仍然能够正常运行;并且在后续发布中要避免修改参数名称,因为参数名称以及成为了公有接口的一部分。