這篇文章裡,用il語言解釋一下static方法和non-static方法在調用的時候,堆棧頂部傳遞參數的不同形式。
首先看一段代碼:
class TestClass
{
public static readonly int i = 10;
static void Main(string[] args)
{
TestClass testClass = new TestClass();
TestStatic();
testClass.NonStatic();
}
public static void TestStatic()
{
}
public void NonStatic()
{
}
}
反編譯以後得到:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 21 (0x15)
.maxstack 1
.locals init ([0] class TestConcoleApp.TestClass testClass)
IL_0000: nop
IL_0001: newobj instance void TestConcoleApp.TestClass::.ctor()
IL_0006: stloc.0
IL_0007: call void TestConcoleApp.TestClass::TestStatic()
IL_000c: nop
IL_000d: ldloc.0
IL_000e: callvirt instance void TestConcoleApp.TestClass::NonStatic()
IL_0013: nop
IL_0014: ret
} // end of method TestClass::Main
首先,關於this pointer,可以參考ibm的文檔:
http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr035.htm
注意藍色的這一行。這一行說明了一個問題,在使用static方法和non-static方法的時候,static方法並不pass this pointer到stack中去。而non-static方法確需要傳遞一個instance的reference到stack中去。
因為,在
IL_0001: newobj instance void TestConcoleApp.TestClass::.ctor()
IL_0006: stloc.0
指令中,儲存了新執行個體化的一個變數到loc.0中去了,然後在調用static方法的時候,堆棧的頂部是沒有obj的reference的。而調用non-static方法的時候,需要傳遞一個obj的reference到堆棧的頂部去。
如果大家想繼續深入瞭解為什麼static方法不需要傳遞一個obj的reference,可以參考compile time 和 run time的區別,下面是一篇ibm的文檔:
http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlcpp8l.doc/proguide/ref/cvfltar.htm