zoukankan      html  css  js  c++  java
  • C#函数的默认参数——填坑记

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

    过程是这样的。

    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

  • 相关阅读:
    mysql 创建++删除 数据表
    mac 配置apache
    mac 安装mysql
    mysql 创建++删除 数据库
    配置默认编码为utf8
    mysql 添加用户
    mysql 查看库结构---查看表结构
    centos7
    centOS 7 安装mysql
    修改字符集
  • 原文地址:https://www.cnblogs.com/icyJ/p/DefaultParams.html
Copyright © 2011-2022 走看看