1. 程式人生 > >VS編譯間接引用的DLL不一定輸出

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

轉載請註明出處。