VS編譯間接引用的DLL不一定輸出
如果A引用B,B引用C,那麼A對C就是間接引用,一般的編譯A時會輸出B的DLL,而因為B對C有引用,所以也會輸出C的DLL。但是實際編譯時發現,並不一定都會輸出C的DLL。後面不斷的追查原因,最終發現是與B對C引用時程式碼的呼叫有關。如果B對C的呼叫都是常量的方式,比如C中都是CONST常量,或者B只調用了C的CONST常量。那麼編譯的時候,B不會帶上C的引用,這個可以ildasm工具,去檢視B的DLL,然後可以看到引用的情況。
先來看C庫的程式碼
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace C { public sealed class ClassC { public const string TC = "MY_CONST"; } }
再來看B庫的程式碼
using C;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace B
{
public class ClassB
{
public static string TestB()
{
return ClassC.TC + "=>call C ok";
}
}
}
再來看C的程式碼
using B; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace A { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { var str = ClassB.TestB(); MessageBox.Show(str); } } }
A是winform程式,執行後的結果如下圖
執行的結果是我們所期望的,那我們現在用ildasm來檢視B編譯生成的DLL
可以看到根本沒有對C程式集的引用。那為什麼程式碼卻正確執行了呢?我們可以看B的TestB方法被編譯後的情況,如下圖
從圖上可以看到程式碼中ClassC.TC已經被常量"MY_CONST"取代了,所以程式碼能夠正常執行。
VS在編譯的時候進行了智慧的判斷,在所有的常量都被替換成具體的值之後,沒有再進行呼叫,比如方法、建構函式等,所以A引用B,B引用C,A對C雖然是間接引用,但是根本不需要該DLL,下面是A編譯後的檔案列表。
而B編譯的結果卻是C的DLL一定會輸出的。
那麼什麼情況下又會將間接引用的C編譯出來呢?只要B對C有方法或者可變數的呼叫就會編譯輸出C的DLL。比如C中將const常量改成static常量。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace C
{
public sealed class ClassC
{
public static string TC = "MY_CONST";
}
}
這時A中編譯的結果如下
可以看到C的DLL被編譯輸出了。再用ildasm來看B中的引用情況。
可以看到有對C的引用。再看B中TestB方法的編譯情況
B中呼叫ClassC的TC變數。這也從側面說明const和static是不一樣的,有的文章說const最終會被編譯成static的常量,從這個角度來看,這個觀點是有待商榷的。也有可能是舊版的VS是這樣處理的,而新版的VS採用了新的編譯策略。所用的VS截圖如下
關於間接引用,大家還可以參考該文章。
https://www.cnblogs.com/gates/p/3224794.html
轉載請註明出處。