昨天踩了一个坑。默认参数 + 增量发布的坑。

过程是这样的。

1. 有一个底层的方法,格式形如

void Test<T>(int p1, string p2, Func<T> p3){}

代码所在的项目的程序集名称假设为 A.dll

2. 引用这个方法的代码有多处,大部分分布在两个项目里面,对应的项目的程序集假设为B.dll和C.dll

3. 处于优化和解决bug的考虑,扩展了上述底层方法,改为:

void Test<T>(int p1, string p2, Func<T> p3, Func<T, bool> p4 = null){}

增加了第四个有默认值得参数。

这里提一下自己的理解误区:我一直以为上面的写法是等于:

void Test<T>(int p1, string p2, Func<T> p3){}

+

void Test<T>(int p1, string p2, Func<T> p3, Func<T, bool> p4){}

4. 改完了底层的那个方法后,重新编译获得A.dll,和相应调用了四个参数方法的代码所在的B.dll

5. 增量发布A.dll和B.dll。

...

6. 线上报错,异常信息提示源头为C.dll,异常明细是Method not found '!!0 Test(Int64, System.String, System.Func`1)'

7. 一脸懵逼 + 二脸懵逼 + 。。。 + 关它么事???

8. 差点准备回滚覆盖了。同事提醒,既然说它有问题,就更新它呗。依言照办,线上恢复。

轮到我百思不得其解了,为什么C.dll找不到这个方法呢?A里面不在呢吗?

后来我用反射工具查看了两个C.dll里面的代码。如下:

原始代码:

A.dll改之前,通过反编译看到的此处代码:

A.dll改成带默认参数之后:

重点在后面的那个null值。

也就是说,将函数Test后面追加了一个带默认值的参数后,相应原来调用时没有传第四个参数的地方,本质上是传了参数的,参数值为默认值。而函数的默认参数则像是一种语法糖,替程序员节省了输入null值的步骤,但是编译后的代码中,确实有的。

所以在上面的情况中,增量发布时,必须一起更新C.dll。否则,旧的DLL文件无法调用新的A.dll中的函数了。

补充一个。A.dll的反射获得的信息:

由上面这个图可以清晰的看到,这个函数,只有一个四个传参的定义,没有三个传参的重载。

相关阅读:

https://www.cnblogs.com/gdouzz/p/6889163.html

C#函数的默认参数——填坑记的更多相关文章

  1. Appium+python自动化(十三)- 输入中文 - 一次填坑记(超详解)

    简介 无论你在哪里,在做什么都会遇到很多坑,这些坑有些事别人挖的,有些是自己挖的.别人挖的叫坑人,自己挖的叫自杀,儿子挖的叫坑爹.因此在做app自动化道路上也不会是一帆风顺的,你会踩很多坑,这些坑和你 ...

  2. UiAutomator2.0升级填坑记

    UiAutomator2.0升级填坑记 SkySeraph May. 28th 2017 Email:skyseraph00@163.com 更多精彩请直接访问SkySeraph个人站点:www.sk ...

  3. Android项目开发填坑记-Fragment的onBackPressed

    Github版 CSDN版 知识背景 Fragment在当前的Android开发中,有两种引用方式,一个是 Android 3.0 时加入的,一个是supportV4包中的.这里简称为Fragment ...

  4. 浅谈html5 video 移动端填坑记

    这篇文章主要介绍了浅谈html5 video 移动端填坑记,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 本文介绍了html5 video 移动端填坑记,分享给大家,具体 ...

  5. Python默认参数的坑

    默认参数的坑 定义一个函数,传入一个list,添加一个end再返回 def add_end(L=[]): L.append('END') return L 正常调用时,结果似乎不错 print add ...

  6. Java web 开发填坑记 2 -如何正确的创建一个Java Web 项目

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/72566261 本文出自[赵彦军的博客] Java web 开发填坑记 1-如何正确 ...

  7. C++中函数的默认参数

    使用方法: (1)在函数声明或定义时,直接对参数赋值,该参数就是默认参数. (2)在函数调用时,省略部分或全部参数,这时就会使用默认参数进行代替. 注意事项: (1)一般在声明函数是设置默认参数. 如 ...

  8. Android项目开发填坑记-Fragment的onAttach

    背景 现在Android开发多使用一个Activity管理多个Fragment进行开发,不免需要两者相互传递数据,一般是给Fragment添加回调接口,让Activity继承并实现. 回调接口一般都写 ...

  9. Android项目开发填坑记-so文件引发的攻坚战

    故事的最初 我负责的项目A要求有播放在线视频的功能,当时从别人的聊天记录的一瞥中发现百度有相关的SDK,当时找到的是Baidu-T5Player-SDK-Android-1.4s,项目中Demo的so ...

随机推荐

  1. 关于MVC框架中的Model的理解

    一直以来对MVC结构中的Model层很不理解. 虽然Model层封装了一些方法,在查询和属性访问的时候提供了一些便利,但是实际使用中更多感受到的是Model层带来的限制,用起来十分别扭. 之前继承的一 ...

  2. Idea创建一个springboot多模块项目

    一.创建空Maven项目 二.左边选择maven,右边可以什么不选,直接next: 三.填写artifactId,点击next直到finish 四.finish后,idea会生成如下结果模块,删除sr ...

  3. 【DWM1000】 code 解密10 一 TAG 发送最后一个消息

    更上面ANCHOR发送信息时的RTLS_DEMO_MSG_ANCH_RESP, 我们很快就可以找到如下代码 case RTLS_DEMO_MSG_ANCH_RESP: { 这里面一部分是设置重要变量, ...

  4. select超全超详细总结篇

    1.经常使用到select,每次都是翻翻翻资料,干脆总结一下,方便日后查看.   2.checked     匹配所有选中的被选中元素(复选框.单选框等,不包括select中的option)   se ...

  5. 为什么要DevOps?

    Boss:「项目经常延期」「做东西太慢」 产品: 「老板的想法总变」 「事情太多,忙成狗」 「开发说这个实现不了」 开发: 「需求总变」 「UI 方案给的太晚」 「活儿太多」 测试: 「需求变了没提前 ...

  6. NLP 工具类库

    NLPIR http://www.nlpir.org/ HanLP https://github.com/hankcs Apache OpenNLP   https://opennlp.apache. ...

  7. Jmeter接口测试实例2-获取所有学生信息

    Jmeter实例2:获取所有学生信息 添加http协议—添加IP.路径.方法,添加信息头管理器,察看结果树,运行 如下图所示,响应结果中获取到所有学生信息

  8. ionic2 (真正)修改应用图标和启动画面

    今天在用ionic2 的ionic resources生成新的icon和splash,生成后安装,应用图标和启动画面依然没变化... 不知道大家有没有被坑过,今天被坑了一下午,终于找到了办法: 解决方 ...

  9. Mybatis批量插入返回自增主键(转)

    我们都知道Mybatis在插入单条数据的时候有两种方式返回自增主键: 1.对于支持生成自增主键的数据库:useGenerateKeys和keyProperty. 2.不支持生成自增主键的数据库:< ...

  10. JAVA自学笔记20

    JAVA自学笔记20 1.递归: 1)方法定义中定义中调用方法本身的现象 2)要有出口,否则就是死递归 次数不能太多.否则内存将溢出 构造方法不能递归使用 //斐波那契数列:1,1,2,3,5,8,1 ...