博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
“.NET研究”谈谈C# 4.0新特性“缺省参数”的实现
阅读量:7297 次
发布时间:2019-06-30

本文共 3736 字,大约阅读时间需要 12 分钟。

  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)
{
Console.WriteLine(
"
{0, -5} - {1, -5} - {2, -5}
"
, foo, bar, 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
"
)]
string
baz)
{
//
Others..
}

  正是因为缺省参数的默认值最终是作为DefaultParameterValueAttribute的参数存在的,所以它必须是常量。

  三、直接通过OptionalAttribute和DefaultParameterValueAttribute 定义缺省参数

  既然缺省参数最终体现为OptionalAttribute和DefaultParameterValueAttribute 这两个特性,我们是否可以直接通过它们来定义缺省参数呢?答案是:当然可以,下面的代码一样可以正常执行。

 
static
void
Main(
string
[] args)
{
TestMethod(
"
Foo
"
);
TestMethod(
"
Foo
"
,
"
Bar1
"
);
TestMethod(
"
Foo
"
,
"
Bar1
"
,
"
Baz1
"
);
}
private
static
void
TestMethod(
string
foo,
[Optional, DefaultParameterValue(
"
Bar
"
)]
string
bar,
[Optional, DefaultParameterValue(
"
Baz
"
)]
string
baz)
{
//
Others..
}

  如果调用含有缺省参数的方法,并且没有显示指定该参数,编译器在编译的时候会自动将默认值附加上去。对于上面的Main方法,下面是与之等效的编译后代码。

 
private
static
void
Main(
string
[] args)
{
TestMethod(
"
Foo
"
,
"
Bar
"
,
"
Baz
"
);
TestMethod(
"
Foo
"
,
"
Bar1
"
,
"
Baz
"
);
TestMethod(
"
Foo
"
,
"
Bar1
"
,
"
Baz1
"
);
}

  虽然说我们通过OptionalAttribute和DefaultParameterValueAttribute 这两个特性也可以定义缺省参数,但是当我们将缺省参数定义在普通参数之前是,编译器不会报错。倒是方法中缺省参数实际上就相当于普通参数了。

 
static
void
Main(
string
[] args)
{
//
TestMethod("Foo","Baz");
//
上面的方法调用无效
TestMethod(
"
Foo
"
,
"
Bar1
"
,
"
Baz1 上海徐汇企业网站制作style='color:white;' href='http://www.93tj.com'>上海网站建设"color: #800000;">"
);
}
private
static
void
TestMethod(
string
foo,
[Optional, DefaultParameterValue(
"
Bar
"
)]
string
bar,
string
baz)
{
//
Others..
}

转载于:https://www.cnblogs.com/waw/archive/2011/10/18/2216969.html

你可能感兴趣的文章
我的第一个Scrapy 程序 - 爬取当当网信息
查看>>
Shell脚本中的并发(2)
查看>>
angularjs directive 的几点使用技巧
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
选择排序
查看>>
利用sendmail搭建邮件服务器
查看>>
RHEL 使用centos 源
查看>>
perl 爬ku6视频
查看>>
IE9上特定网站不断崩溃的故障
查看>>
Oracle序列使用:建立、删除
查看>>
我的友情链接
查看>>
秀一秀我的微软MVP(最有价值专家)的大礼包和水晶奖杯!
查看>>
Unix command to find CPU Utilization
查看>>
打开.264后缀名格式的文件
查看>>
MYSQL查看 table 表状态常用的命令
查看>>
Java——容器(Comparable)
查看>>
二叉树的非递归遍历
查看>>
数据库连接客户端使用(db2,oracle,mysql)
查看>>
Spring的事务管理难点剖析:应用分层的迷惑
查看>>