一、背景:
互联网行业,为了降低程序维护、升级的部署风险,往往会将程序拆分成很多项目,编译成多个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. ABP文档 - Hangfire 集成

    文档目录 本节内容: 简介 集成 Hangfire 面板授权 简介 Hangfire是一个综合的后台作业管理器,可以在ABP里集成它替代默认的后台作业管理器,你可以为Hangfire使用相同的后台作业 ...

  2. 04.LoT.UI 前后台通用框架分解系列之——轻巧的弹出框

    LOT.UI分解系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#lotui LoT.UI开源地址如下:https://github.com/du ...

  3. React在开发中的常用结构以及功能详解

    一.React什么算法,什么虚拟DOM,什么核心内容网上一大堆,请自行google. 但是能把算法说清楚,虚拟DOM说清楚的聊聊无几.对开发又没卵用,还不如来点干货看看咋用. 二.结构如下: impo ...

  4. Hawk 6. 编译和扩展开发

    Hawk是开源项目,因此任何人都可以为其贡献代码.作者也非常欢迎使用者能够扩展出更有用的插件. 编译 编译需要Visual Stuido,版本建议使用2015, 2010及以上没有经过测试,但应该可以 ...

  5. Kooboo CMS技术文档之二:Kooboo CMS的安装步骤

    在IIS上安装Kooboo CMS Kooboo CMS安装之后 安装的常见问题 1. 在IIS上安装Kooboo CMS Kooboo CMS部署到正式环境相当简单,安装过程是一个普通MVC站点在I ...

  6. How those spring enable annotations work--转

    原文地址:http://blog.fawnanddoug.com/2012/08/how-those-spring-enable-annotations-work.html Spring's Java ...

  7. 动手做第一个Chrome插件

    Chrome插件是令人惊讶的简单,一旦你弄懂它的工作和实现原理.它是由一部分HTML,一部分Js,然后混合了一个叫做manifest.json的Json文件组合而成的整体.这意味着你可以使用你最擅长的 ...

  8. CSS margin详解

    以下的分享是本人最近几天学习了margin知识后,大有启发,感觉以前对margin的了解简直太浅薄.所以写成以下文章,一是供自己整理思路:二是把知识分享出来,避免各位对margin属性的误解.内容可能 ...

  9. (转载) Linux IO模式及 select、poll、epoll详解

    注:本文是对众多博客的学习和总结,可能存在理解错误.请带着怀疑的眼光,同时如果有错误希望能指出. 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案 ...

  10. FineReport关于tomcat集群部署的方案

    多台服务器集群后,配置权限.数据连接.模板.定时调度等,只能每台服务器一个个配置,不会自动同步到所有服务器. 针对上述情况,在FineReport中提供新集群部署插件,将xml配置文件.finedb/ ...