“.NET研究”谈谈C# 4.0新特性“缺省参数”的实现

  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")] strin上海闵行企业网站设计与制作g 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..
}

时间: 2024-09-20 18:02:42

“.NET研究”谈谈C# 4.0新特性“缺省参数”的实现的相关文章

谈谈C# 4.0新特性“缺省参数”的实现

转自 http://www.cnblogs.com/artech/archive/2011/01/12/optionalparameter.html   C#4.0关于缺省参数的新特性,相信大家都不会陌生.所谓缺省参数,顾名思义,就是在声明方法的某个参数的时候为之指定一个默认值,在调用该方法 的时候如果采用该默认值,你就无须指定该参数.和很多语言层面特性(语法糖)的实现一样,缺省参数也是编译器为我们玩的一个小花招.缺省参数最终体现为两 个特殊的自定义特性OptionalAttribute和Def

一起谈.NET技术,谈谈C# 4.0新特性“缺省参数”的实现

C#4.0关于缺省参数的新特性,相信大家都不会陌生.所谓缺省参数,顾名思义,就是在声明方法的某个参数的时候为之指定一个默认值,在调用该方法的时候如果采用该默认值,你就无须指定该参数.和很多语言层面特性(语法糖)的实现一样,缺省参数也是编译器为我们玩的一个小花招.缺省参数最终体现为两个特殊的自定义特性OptionalAttribute和DefaultParameterValueAttribute . 目录 一.缺省参数的用法 二.实现缺省参数的两个特性:OptionalAttribute和Defa

MySQL · 8.0.0新特性 · 持久化全局参数修改

PS: 本文内容基于MySQL8.0.0版本,由于目前才Release了第一个开发版本,不排除后续行为会发生变化 相信很多朋友都有这样的体验,在实例启动的时候动态修改了某些配置,但是忘了修改配置文件,结果实例一重启修改就丢失了.或者对于诸如部署在云上的业务(例如RDS),通常用户是没有修改配置文件的权限的,这导致配置的设定不够灵活.从MySQL8.0开始,大家不用担心这个问题了,用户可以选择性的将配置进行持久化. 对应的Worklog: WL#8688 启用这个功能,使用特定的语法SET PER

C#4.0新特性 可选命名参数

Code    class Program    {        static void PrintStudents(int id = -1, string name = "*", int age = -1)        {            Console.WriteLine("the student is id:{0} name:{1} age:{2}", id, name, age);        }        static void Main(

c# 6.0新特性(一)

写在前面 接近年底了,基本上没什么活了,就学点新东西,就想着了解下c# 6.0的新特性.在code project上看到了一篇不错的文章,就准备翻译一下,顺便照着学习学习.废话不多说,直奔主题. 原文地址:http://www.codeproject.com/Articles/1070659/All-About-Csharp-New-Features 简介 众所周知,c# 6.0 是在visual studio 2015中引入的.在其他的几个版本中同样引入一些特性,比如在c# 3.0中引入了li

MySQL 5.0 新特性--存储过程

Introduction 简介 MySQL 5.0 新特性教程是为需要了解5.0版本新特性的MySQL老用户而写的.简单的来说是介绍了"存储过程.触发器.视图.信息架构视图",在此感谢译者陈朋奕的努力. 希望这本书能像内行专家那样与您进行对话,用简单的问题.例子让你学到需要的知识.为了达到这样的目的,我会从每一个细节开始慢慢的为大家建立概念,最后会给大家展示较大的实用例,在学习之前也许大家会认为这个用例很难,但是只要跟着课程去学,相信很快就能掌握. Conventions and St

MySQL5.0新特性教程 存储过程:第三讲

The New SQL Statements 新SQL语句 Variables 变量 在复合语句中声明变量的指令是DECLARE. (1) Example with two DECLARE statements 两个DECLARE语句的例子 WHILE ... END WHILE CREATE PROCEDURE p8 () BEGIN DECLARE a INT; DECLARE b INT; SET a = 5; SET b = 5; INSERT INTO t VALUES (a); SE

PHP 5昨天隆重推出--PHP 5/Zend Engine 2.0新特性

前言    今天突然想到PHP官方网站上一转,一眼就看到PHP5推出的通告.虽然以前看到过PHP5的预告,但还是仔细看了PHP 5/Zend Engine 2.0新特性一文,一股JAVA气息扑面而来...   特将该文试译出来,首发于CSDN网站,以飨读者. PHP 5/Zend Engine 2.0新特性徐唤春 译 sfwebsite@hotmail.comhttp://www.php.net/zend-engine-2.php 全新的对象模型PHP中的对象处理部分已完全重写,具有更佳的性能和

MySQL 5.0新特性教程 存储过程:第一讲

mysql|存储过程|教程 作者:mysql AB;翻译:陈朋奕 Introduction 简介 MySQL 5.0 新特性教程是为需要了解5.0版本新特性的MySQL老用户而写的.简单的来说是介绍了"存储过程.触发器.视图.信息架构视图",在此感谢译者陈朋奕的努力. 希望这本书能像内行专家那样与您进行对话,用简单的问题.例子让你学到需要的知识.为了达到这样的目的,我会从每一个细节开始慢慢的为大家建立概念,最后会给大家展示较大的实用例,在学习之前也许大家会认为这个用例很难,但是只要跟着