第 9 章 参数
第 9 章 参数
NyxX第 9 章 参数
本章内容:
9.1 可选参数和命名参数
规则和原则
如果在方法中为部分参数指定了默认值,请注意以下附加的规则和原则。
- 可为方法、构造器方法和有参属性(C#索引器)的参数指定默认值。还可以属于委托定义一部分的参数指定默认值。以后调用该委托类型的变量时可省略实参来接受默认值。
- 有默认值的参数必须放在没有默认值的所有参数之后。“参数数组”这种参数必须放在所有参数(包括有默认值的这些)之后,而且数组本身不能有一个默认值。
- 默认值必须是编译时能确定的常量值。这些参数的类型可以是C# 认定的基元类型、枚举类型、能设为
null的任何引用类型。 - 不要重命名参数变量
- 如果方法从模块外部调用,更改参数的默认值具有潜在的危险性。
- 如果参数用
ref或out关键字进行了标识,就不能设置默认值。 - 实参可按任意顺序传递,但命名实参只能出现在实参列表的尾部。
- 可按名称将实参传给没有默认值的参数,但所有必须的实参都必须传递(无论按位置还是按名称),编译器才能编译代码。
- C# 不允许省略逗号之间的实参
- 如果参数要求
ref/out,为了以传参数名的方式传递实参,请使用下面这样的语法:
1 | // 方法声明 |
9.1.2 DefaultParameterValueAttribute 和 OptionalAttribute
在 C# 中,一旦为参数分配了默认值,编译器就会在内部向该参数应用定制特性System.Runtime.InteropServices.OptionalAttribute。该特性会在最终生成的文件的元数据中持久性地存储下来。此外,编译器向参数应用 System.Runtime.InteropServices.DefaultParameterValueAttribute 特性,并将该属性持久性存储到生成的文件的元数据中。然后,会向 DefaultParameterValueAttribute 的构造器传递你在源代码中指定的常量值。
之后,一旦编译器发现某个方法调用缺失了部分实参,就可以确定省略的是可选的实参,并从元数据中提取默认值,将值自动嵌入调用中。
9.2 隐式类型的局部变量
用var声明局部变量只有一种简化语法,它要求编译器根据表达式推断具体数据类型
var 和 dynamic 的区别
var关键字只能声明方法内部的局部变量,而dynamic关键字适用于局部变量、字段和参数。- 表达式不能转型为
var,但能转型为dynamic。 - 必须显式初始化用
var声明的变量,但无需初始化用dynamic声明的变量。
9.3 以传引用的方式向方法传递参数
CLR 允许以传引用而非传值的方式传递参数。C# 用关键字 out 或 ref 支持这个功能。
CLR 不区分 out 和 ref,意味着无论用哪个关键字,都会生成相同的 IL 代码。另外,与那数据也几乎完全一致,只有一个 bit 除外,它用于记录声明方法时指定的是 out 还是 ref。
如果方法的参数用 out 来标记,表明不指望调用者在调用方法之前初始化好了对象。被调用的方法不能读取参数的值,而且在返回前必须向这个值写入。
如果方法的参数用 ref 来标记,调用者就必须在调用该方法前初始化参数的值,被调用的方法可以读取值以及/或者向值写入。
9.4 向方法传递可变数量的参数
为了接受可变数量的参数,方法要像下面这样声明:
1 | static Int32 Add(params Int32[] values) { |
9.5 参数和返回类型的设计规范
声明方法的参数类型时,应尽量指定最弱的类型,宁愿要接口也不要基类。
一般最好是将方法的返回类型声明为最强的类型
9.6 常量性
有的语言(比如非托管 C++)允许将方法或参数声明为常量,从而禁止实例方法中的代码更改对象的任何字段,或者更改传给方法的任何对象。CLR 没有提供这个功能。





