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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM