c#可选参数的一个陷阱

一、背景:

互联网行业,为了降低部署风险,往往会将程序拆分成很多项目,编译成多个dll部署,这样修改的时候,只需要部署修改过的dll即可。

二、问题:

有一个函数,在很多个地方被使用:

public fun1(A a ,B b)
{
    //代码主体
}

突然有一天,有的地方调用的时候需要加入一个参数C c,但是又不想其他客户程序有任何变动,可以这样改:

方法一:使用可选参数

public fun1(A a ,B b,C c = 1)
{
 //代码主体
}

程序修改完后,在本地程序完美运行,将dll发测试。在测试环境,莫名其妙的报错。由于系统分层处理,web站点和Web API分离,错误返回到最上层,已经看不到错误原因,查了老半天日志,终于发现是另外一个dll调用了fun1函数,报找不到方法 fun1的错误。

将程序修改为:

方法二:重载

public fun1(A a ,B b)
{
    fun1(A a ,B b,1);
}
public fun1(A a ,B b,C c)
{
   //代码主体
}

重新发布dll,程序正常运行。

三、初步结论:

将代码修改成可选参数,客户程序需要重新编译,不然客户程序调用的时候会报找不到方法的错误。如果,客户程序太多,为了避免部署所有客户程序的dll,可以用方法二,重载的方法。

四、验证:

方法无默认参数:

方法有可选参数:

客户程序Program编译后的IL:

五、最终结论:

由图可知,客户程序的c#源码虽然没有变,但是编译后的IL中间代码确改变了,调用的函数也传了两个参数,并把函数默认参数888在客户程序声明,使用。

可以得出的结论是,C#可选参数函数其实是在编译的时候,在函数调用的地方做了处理,把默认参数传了进去。

六、现在问题来了,大家请思考

微软为什么要这样做呢?为什么不在编译的时候,像以下代码一样,做类似重载的处理呢? 这样的话就不用重新编译客户程序了

public fun1(A a ,B b)
{
    fun1(A a ,B b,1);
}
public fun1(A a ,B b,C c)
{
   //代码主体
}
时间: 2024-10-02 09:17:43

c#可选参数的一个陷阱的相关文章

None还可以是函数定义可选参数的一个默认值,设置成默认值时实参在调用该函数时可以不输入与None绑定的元素

1 >>> def add_and_maybe_multiply(a,b,c=None): 2 result = a+b 3 if c is not None: 4 result = result*c 5 return result 6 7 >>> add_and_maybe_multiply(2,3,' ')#实参为空格,返回空格 8 ' ' 9 >>> add_and_maybe_multiply(2,3,'')#实参为空,返回为空 10 '' 1

【转】C#具名参数和可选参数

源地址:https://www.cnblogs.com/similar/p/5006705.html 另:可选参数的一个陷阱 参考:https://www.cnblogs.com/still-windows7/p/kexuancanshuxianjing.html 原文地址:https://www.cnblogs.com/haizine/p/10567291.html

C#:可选参数的陷阱 [转]

一.背景: 互联网行业,为了降低程序维护.升级的部署风险,往往会将程序拆分成很多项目,编译成多个dll部署,这样发布的时候,只需要部署修改过的dll即可. 二.问题: 有一个函数,在很多个地方被使用: public fun1(A a ,B b) { //代码主体 } 突然有一天,有的地方调用的时候需要加入一个参数C c,但是又不想其他客户程序有任何变动,可以充分利用.net4.0新增的可选参数特性,这样改: 方法一:使用可选参数 public fun1(A a ,B b,C c = 1) { /

C#使用异步委托在另一个线程上更新窗体不能省略可选参数

使用button1更新label1: private delegate void UpdateFormInvoke(string a, string b = "B"); private void UpdateForm(string a, string b = "B") { label1.Text = a + " - " + b; } private void button1_Click(object sender, EventArgs e) {

c# 方法参数(传值,传引用,ref,out,params,可选参数,命名参数)

 一.方法参数的类型----值类型和引用类型 当方法传递的参数是值类型时,变量的栈数据会完整地复制到目标参数中即实参和形参中的数据相同但存放在内存的不同位置.所以,在目标方法中对形参所做的更改不会对调用者的初始变量产生任何影响. 当方法传递的参数是引用类型是,只是将变量的引用复制到目标参数中,实参和形参的引用指向内存中的同一位置.所以,在目标方法中对形参所做的更改会影响调用者的初始变量. 二.一些特殊的方法参数 1.引用参数---ref (使值类型的变量做方法参数时也可以传引用) 一些数据类型(

可选参数、命名参数、.NET的特殊类型、特性

1.可选参数和命名参数    1.1可选参数        语法:            [修饰符] 返回类型 方法名(必选参数n,可选参数n)        注意:            1.必选参数可以不存在,也可以有多个:可选参数可以有1个或多个            2.可选参数必须放在必选参数之后            3.可选参数在定义时需要赋初始值            4.可选参数之间也需要使用,进行分隔            5.调用可选参数时,不能跨参数赋值    1.2命名

jQuery form插件的使用--ajaxForm()和ajaxSubmit()的可选参数项对象

一.前提说明 Form Plugin API 里提供了很多有用的方法可以让你轻松的处理表单里的数据和表单的提交过程. 测试环境:部署到Tomcat中的web项目. 二.简单介绍 本文演示的是:jQuery form插件的使用--ajaxForm()和ajaxSubmit()的可选参数项对象 $('#myForm').ajaxForm(function() { $('#output1').html("提交成功!欢迎下次再来!").show(); }); $('#myForm2').sub

MSSQL中存储过程的可选参数的定义和使用

可选参数的存在,可以极大的降低代码的重复冗余.在数据库开发中,也是如此.现在针对MSSQL中存储过程的可选参数的定义和使用进行基本的介绍,留作备忘. #准备工作: 在db_test中建立一张测试表T_test: USE db_test; CREATE TABLE dbo.T_test ( Id  INT  IDENTITY(1,1) NOT NULL ,Name  NVARCHAR(20)  NOT NULL ,Sex  BIT  DEFAULT(0) ); 插入一些数据: INSERT INT

ylbtech-LanguageSamples-NamedAndOptional(命名和可选参数)

ylbtech-Microsoft-CSharpSamples:ylbtech-LanguageSamples-NamedAndOptional(命名和可选参数) 1.A,示例(Sample) 返回顶部 命名和可选参数 C# 4.0 支持命名和可选参数. 此程序演示如何声明一个具有命名和可选参数的方法,以及如何通过使用参数的默认值和通过显式命名特定参数来调用该方法. 1.B,示例代码(Sample Code)返回顶部 1.B.1, Program.cs using System; using S