如果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
转载请注明出处。