一、背景:
互联网行业,为了降低程序维护、升级的部署风险,往往会将程序拆分成很多项目,编译成多个dll部署,这样发布的时候,只需要部署修改过的dll即可。
 
二、问题:
有一个函数,在很多个地方被使用:
public fun1(A a ,B b)
{
//代码主体
}
突然有一天,有的地方调用的时候需要加入一个参数C c,但是又不想其他客户程序有任何变动,可以充分利用.net4.0新增的可选参数特性,这样改:
方法一:使用可选参数
public fun1(A a ,B b,C c = )
{
//代码主体
}
程序修改完后,在本地程序完美运行,将dll发测试。在测试环境,莫名其妙的报错。由于系统分层处理,web站点和Web API分离,错误返回到最上层,已经看不到错误原因,查了老半天日志,终于发现是另外一个dll(未重新编译部署)调用了fun1函数,报找不到方法 fun1的错误。
 
 
将程序修改为:
方法二:重载
public fun1(A a ,B b)
{
fun1(A a ,B b,);
}
public fun1(A a ,B b,C c)
{
//代码主体
}
重新发布dll,程序正常运行。
 
三、初步结论:
 
将代码修改成可选参数,客户程序需要重新编译,不然客户程序调用的时候会报找不到方法的错误。如果,客户程序太多,为了避免部署所有客户程序的dll,可以用方法二,重载的方法。
 
四、验证:
方法无默认参数:
 
 
 
方法有可选参数:
 
客户程序Program编译后的IL:
 
 
五、最终结论:
     由图可知,客户程序的c#源码虽然没有变,但是编译后的IL中间代码确改变了,调用的函数也传了两个参数,并把函数默认参数888在客户程序声明,使用。
可以得出的结论是,C#可选参数函数其实是在编译的时候,在函数调用的客户程序做了处理,把默认参数传了进去。
 
六、现在问题来了,大家请思考
微软为什么要这样做呢?为什么不在编译的时候,IL像以下代码一样,做类似重载的处理呢? 这样的话就不用重新编译客户程序了
 
public fun1(A a ,B b)
{
fun1(A a ,B b,);
}
public fun1(A a ,B b,C c)
{
//代码主体
}

七、网友解答:感谢34楼CYJB和其他网友的热心解答,非常详尽

楼主为方法添加了一个默认参数,那么这个新的方法和之前的方法的签名是完全不同的——对应的参数个数是不同的,所以才会出现找不到方法的错误。.Net 里的可选参数就像 @冲杀 说的,就是一个语法糖,仅仅是编译器在方法调用的时候自动加上了默认参数值而已,编译器完全可能不支持这一功能。

实际上,根据 VS “代码分析”功能,可以发现公共方法使用默认参数,是具有一定风险的,因为:在公共语言规范 (CLS) 中允许方法使用默认参数;但是 CLS 允许编译器忽略为这些参数分配的值。 为忽略默认参数值的编译器编写的代码必须为每个默认参数显式提供变量。 为了跨编程语言维护所需的行为,必须使用提供默认参数的方法重载来替换使用默认参数的方法。完整的文档可以参考 MSDN CA1026:不应使用默认参数

最后,公共方法的确是应该只扩展不修改的,以保持良好的兼容性,楼主应该是没有想到 C# 的默认参数只是一个语法糖,而不慎中招了。而微软为何没有将默认方法实现为多个重载,不是不愿,而是不能。例如下面的方法:

public void TestMethod(int a = , int b = , int c = )
{
// ...
}

如果自动实现为多个重载,显然是不可能的,因为参数的类型都是 int,无法根据参数类型来区分出参数 a、b 和 c,因此微软会完全放弃这个方案。而代码膨胀之类的,可能也在微软的考虑范围内。

 

小知识:C#可选参数的一个陷阱的更多相关文章

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

    源地址:https://www.cnblogs.com/similar/p/5006705.html 另:可选参数的一个陷阱 参考:https://www.cnblogs.com/still-wind ...

  2. $Django 路飞之小知识回顾,Vue之样式element-ui,Vue绑定图片--mounted页面挂载--路由携带参数

    一 小知识回顾 1 级联删除问题 2 一张表关联多个表,比如有manytomanyfileds forignkey,基于对象查询存在的问题:反向查询的时候  表名小写_set.all()不知是哪个字段 ...

  3. Java异常的一个小知识

    有以下两个代码: package com.lk.A; public class Test3 { public static void main(String[] args) { try { int a ...

  4. 我总结的js方面你可能不是特别清楚的小知识

    !!将一个值方便快速转化为布尔值 console.log( !!window===true ); 不声明第三个变量实现交换 var a=1,b=2; a=[b,b=a][0];//执行完这句代码之后 ...

  5. wndows程序设计之书籍知识与代码摘录-封装一个类似printf的messagebox

    //----------------------------------------- //本程序展示了如何实现MessageBoxPrintf函数 //本函数能像printf那样格式化输出 //摘录 ...

  6. [读书笔记]C#学习笔记七: C#4.0中微小改动-可选参数,泛型的可变性

    前言 下面就开始总结C#4.0的一些变化了, 也是这本书中最后的一点内容了, 这一部分终于要更新完了. 同时感觉再来读第二遍也有不一样的收获. 今天很嗨的是武汉下雪了,明天周六,一切都是这么美好.哈哈 ...

  7. Xcode 中关于"#"的小知识

    在代码中使用Autolayout时,大家都会使用NSDictionaryOfVariableBindings这个宏,这个宏可以生成一个变量名到变量值映射的Dictionary.比如NSDictiona ...

  8. s性能优化方面的小知识

    总结的js性能优化方面的小知识 前言 一直在学习javascript,也有看过<犀利开发Jquery内核详解与实践>,对这本书的评价只有两个字犀利,可能是对javascript理解的还不够 ...

  9. JS的基本类型(小知识)

    一:js中的基本类型: 基本类型:boolen, string ,number,null,undefined 引用类型:object,和函数 二.undedifned和null的区别: 1 undef ...

随机推荐

  1. PHP实现RTX发送消息提醒

    RTX是腾讯公司推出的企业级即时通信平台,大多数公司都在使用它,但是我们很多时候需要将自己系统或者产品的一些通知实时推送给RTX,这就需要用到RTX的服务端SDK,建议先去看看RTX的SDK开发文档( ...

  2. iOS系列文章

    本博客全为原创,如果借鉴了其他文章会在博文的下面进行说明.欢迎转载,但要在文章中给出原文链接,谢谢. 有链接的说明已经发布,没有链接的说明还没有发布. 并不是所有的博文都在这里罗列,有兴趣的可以看博客 ...

  3. Android注解使用之注解编译android-apt如何切换到annotationProcessor

    前言: 自从EventBus 3.x发布之后其通过注解预编译的方式解决了之前通过反射机制所引起的性能效率问题,其中注解预编译所采用的的就是android-apt的方式,不过最近Apt工具的作者宣布了不 ...

  4. [C#][算法] 用菜鸟的思维学习算法 -- 马桶排序、冒泡排序和快速排序

    用菜鸟的思维学习算法 -- 马桶排序.冒泡排序和快速排序 [博主]反骨仔 [来源]http://www.cnblogs.com/liqingwen/p/4994261.html  目录 马桶排序(令人 ...

  5. H5程序员如何利用cordova开发跨平台应用

    什么是Cordova? Cordova以前也叫PhoneGap,它提供了一组设备相关的API,通过这组API,移动应用能够以JavaScript访问原生的设备功能,如摄像头.麦克风等.Cordova还 ...

  6. Kooboo CMS技术文档之一:Kooboo CMS技术背景

    语言平台 依赖注入方案 存储模型 1. 语言平台 Kooboo CMS基于.NET Framework 4.x,.NET Framework 4.x的一些技术特性成为站点开发人员使用Kooboo CM ...

  7. php实现的分页类

    php分页类文件: <?php /** file: page.class.php 完美分页类 Page */ class Page { private $total; //数据表中总记录数 pr ...

  8. 关于Visual Studio 未能加载各种Package包的解决方案

    问题: 打开Visual Studio 的时候,总提示未能加载相应的Package包,有时候还无法打开项目,各种提示 解决方案: 进入用户目录 C:\Users\用户名\AppData\Local\M ...

  9. The Zen of Python

    Beautiful is better than ugly. 优美总比丑陋好Explicit is better than implicit. 直率总比含蓄好Simple is better than ...

  10. java统计字符串单词的个数

    在一些项目中可能需要对一段字符串中的单词进行统计,我在这里写了一个简单的demo,有需要的同学可以拿去看一下. 本人没怎么写个播客,如果有啥说的不对的地方,你来打我啊 不说废话了直接贴代码: 实现代码 ...