命名参数允许调用者通过提供参数的名称来为其赋值这样参数的位置就不在重要了可选参数允许在定义时为某些参数赋值在调用时可以忽略这些可选的参数命名参数和可选参数可以应用在方法索引器构造函数和委托命名参数和可选参数与dynamic类型结合在一起使用可以方便的访诸如Office自动化API之类的COM API
命名参数
命名参数的语法为
参数名称:参数值参数名称:参数值…
例如以下代码
static void Main(string[] args)
{
CreateUser(password:adminpasswordname:admin);
}
static void CreateUser(string name string password)
{
ConsoleWriteLine(name:{}password:{} name password);
}
可以看到由于在调用时使用了命名参数参数的位置就不在重要了
可选参数
方法构造函数索引器和委托的定义可以指定其参数为必选的还是可选的在调用时必须提供必选参数但是可以省略可选参数
还可以使用SystemRuntimeInteropServicesOptionalAttribute特性类定义可选参数该类从时代就已经包含在基类库中了
每一个可选参数的定义都包含默认值(默认值必须是常量)如果在调用时没有指定该参数则使用默认值例如以下代码
static void Main(string[] args)
{
CreateUser(adminadminpassword);
}
/// /// 创建用户
///
///
用户名称
///
用户密码
///
积分
///
是否锁定
static void CreateUser(string name string password
int score=bool isLocked=false)
{
ConsoleWriteLine(name:{}password:{} name password);
}
在所有必须参数后面定义可选参数如果在调用时提供了某个可选参数的值那么必须提供该可选参数之前所有可选参数的值(如果此参数之前有可选参数)而不允许使用逗号分隔的形式提供参数即以下调用是错误的
CreateUser(adminadminpasswordtrue);
而必须写成
CreateUser(adminadminpasswordtrue);
或者更好的解决办法是使用命名参数
CreateUser(adminadminpasswordisLocked:true);
COM API访问
命名和可选参数与dynamic和其他增强一起使得访问COM API更加方便例如在C#或更早的版本中在调用某些COM API时如果要省略某些参数需要使用TypeMissing例如以下代码(代码系摘抄)
var excelApp = new MicrosoftOfficeInteropExcelApplication();
var myFormat =
MicrosoftOfficeInteropExcelXlRangeAutoFormatxlRangeAutoFormatAccounting;
excelAppget_Range(A B)AutoFormat(myFormat TypeMissing
TypeMissing TypeMissing TypeMissing TypeMissing TypeMissing);
但是有了命名和可选参数后可以很简单的写成这样
excelAppget_Range(A B)AutoFormat( Format: myFormat );
类型等价支持(Type Equivalence Support)(此段为翻译)
如果嵌入来自于强命名托管程序集的类型信息时可以使在某一应用程序中的类型与独立的发布版本中类型保持松散的连接这意味着应用程序可以在不需要重新编译每一个版本的情况下使用多个版本托管类库中的类型
类型嵌入经常用于COM交互例如使用Microsoft Office中的自动化的应用程序嵌入类型信息允许同一个应用程序在安装了不同的Office版本的机器上运行而且开发人员可以在完全托管解决方案中使用类型嵌入
来自于某个程序中可以嵌入的类型需要满足以下条件
该程序集至少暴露一个公共接口
该嵌入接口使用ComImport和Guid特性声明
该程序集使用ImportedFromTypeLib和一个程序集级别的Guid特性标注(默认情况下Visual Basic和Visual C#模版已包含了程序集的Guid特性)
在指定可以嵌入的公共接口后可以创建实现了这些接口的类客户端程序可以在设计时引用包含了这些公共接口的程序何并且默认Embed Interop Types属性为true以嵌入类型信息(在命令行使用/link编译开关可以达到相同的效果)接下来客户端可以创建这些接口的实例如果您创建了强命名运行时程序集的新版本
客户端不需要使用新的程序集重新编译相反客户端程序通过公共接口的嵌入类型信息继续使用可用的程序集的版本
首先创建一个强命名接口类库(根据满足条件设置属性)
[ComImport]
[Guid(DAABFDF)]
public interface ISampleInterface
{
void GetUserInput();
string UserInput { get; }
}
创建强命名类库引用接口类库并定义实现以上接口的类
public classSampleClass: ISampleInterface
{
private stringp_UserInput;
public stringUserInput { get{ return p_UserInput; } }
public voidGetUserInput()
{
ConsoleWriteLine(Please enter a value:);
p_UserInput = ConsoleReadLine();
}
}
创建客户端应用程序引用接口并使用反射的方法动态创建类型执行相应操作
class Program
{
static void Main(string[] args)
{
Assembly sampleAssembly = AssemblyLoad(TypeEquivalenceRuntime);
ISampleInterface sampleClass =
(ISampleInterface)sampleAssemblyCreateInstance(TypeEquivalenceRuntimeSampleClass);
sampleClassGetUserInput();
ConsoleWriteLine(sampleClassUserInput);
ConsoleWriteLine(sampleAssemblyGetName()VersionToString());
ConsoleReadLine();
}
}
修改实现了接口在的客户端类增加新的方法并修改程序集版本号和文件版本号为
public DateTime GetDate()
{
return DateTimeNow;
}
再次执行客户端程序观察不同(客户端将输出新的版本号)
在NET全部使用托管代码创建的程序集自动会识别更新也就是说不需要使用额外的属性定义直接创建接口实现接口类库和客户端类(或者没有接口直接创建类库在客户端引用)在类库更新后复制到客户端引用的位置客户端会自动检测到该更新这也是NET程序集为开发人员带来的好处但是使用类型等价支持的作用体现在什么地方我认为还是方便了COM API的访问因为COM可能是使用其他语言编写的没有办法做到像NET程序集那样自动感应版本变化个人意见期望高手解答
总结
Visual C#中提供了动态类型命名参数可选参数和类型等价支持为编程带来便利对于访问COM API来说更方便了而且微软多次提到了诸如Office之类的文字是不是意味着微软在不断的鼓励程序员不断开发出其于Office的一些应用亦或是现在其于Office的应用在不断增加还是应用程序中与Office的交互在不断增加通过增强的特性使这些工作更方便来巩固微软件地位?一家之言请高手不吝赐教