2013-10-01 55 views
4

有人可以解釋以下代碼的工作原理嗎?編譯器如何用postfix操作符處理返回語句?

static int index = 0; 
public static int GetNextIndex() 
{ 
    return index++; 
} 

我認爲,由於增量操作發生在return語句之後,變量'index'永遠不會增加。

但是,當用C#編譯器測試時,我觀察到'索引'正在增加。

標準編譯器如何處理這種情況?

+6

什麼讓你覺得增量發生在return語句之後?增量發生在獲得索引的值後,*在return語句中使用* –

+0

因爲它是後綴運算符。 – Curious

+3

@Fadi閱讀此解答由Eric Lippert解釋pre/postfix的機制http://stackoverflow.com/a/3346729/860585 – Rotem

回答

6

這中間語言(IL),編譯器生成(VS2013RC/.NET 4.5.1RC):

.method public hidebysig static int32 GetNextIndex() cil managed 
{ 
    .maxstack 8 
    L_0000: ldsfld int32 ConsoleApplication4.Program::index 
    L_0005: dup 
    L_0006: ldc.i4.1 
    L_0007: add 
    L_0008: stsfld int32 ConsoleApplication4.Program::index 
    L_000d: ret 
} 

那麼,是什麼呢?假設index在調用它之前的值爲6。

L_0000: ldsfld int32 ConsoleApplication4.Program::index 

加載的index值到計算堆棧 - 堆棧包含6

L_0005: dup 

複製在堆棧的頂部的值 - 堆棧包含6, 6

L_0006: ldc.i4.1 

負載值1到堆棧 - 堆棧包含6, 6, 1

L_0007: add 

增加頂部的兩個值在堆棧上,並將結果放回堆棧。堆棧包含6, 7

L_0008: stsfld int32 ConsoleApplication4.Program::index 

存儲堆棧頂部的值成indexindex現在等於7,堆棧包含6

L_000d: ret 

將棧頂值(6)作爲返回值。

6
static int index = 0; 
public static int GetNextIndex() 
{ 
    return index++; 
} 

相當於:

static int index = 0; 
public static int GetNextIndex() 
{ 
    int i = index; 
    index = index + 1; 
    return i; 
} 

因此index遞增。

+0

好吧,它大部分是相同的。從技術上講,第一個代碼片段只在整個方法中評估表達式'index' *一次;你評估它三次,但它非常接近。 – Servy

+0

如果索引不是** int字段**,則這不等價。評估一個'int'字段沒有副作用。 –

+0

對於三種情況中的一種,即它被分配的情況,它沒有問題,因爲它沒有副作用。但是,您正在讀取兩次'index'的值,並且可能會在這兩個讀取之間更改(從另一個線程中的操作)。第一個代碼片段不會從它讀取兩次,所以它不會觀察到這樣的變化。當然,如果評估表達會導致副作用,那麼整個事情會變得更加不同。 – Servy