2011-04-06 48 views
6

我最近正在研究CancellationToken結構的內部結構,並發現了一些奇怪的結構(更準確地說,將值賦給this關鍵字)。將結構值賦值給這個關鍵字

它的構造函數的一個準則是如下:

public CancellationToken(bool canceled) 
{ 
    this = new CancellationToken(); 
    if (canceled) 
    { 
     this.m_source = CancellationTokenSource.InternalGetStaticSource(canceled); 
    } 
} 

什麼是發生在分配this關鍵字行的意義?

請注意,分配到this關鍵字是不可能的類 - 錯誤Cannot assign to '<this>' because it is read-only發生。

回答

6

這是C#的一個鮮爲人知的特性 - 它允許結構覆蓋自己的數據。我不確定這是否只適用於blittable值類型或不(猜測不)。

至於實際應用中去,你不會找到許多用途爲這個..

struct MyStruct 
{ 
    int a = 1; 
    int b = 2; 
    int c = 3; 

    public void Mutate() 
    { 
     a = 10; 
     b = 20; 
     c = 30; 
    } 

    public void Reset() 
    { 
     a = 1; 
     b = 2; 
     c = 3; 
    } 

    public void Reset2() 
    { 
     this = new MyStruct(); 
    } 

    // The two Reset methods are equivilent... 
} 

更多關於它的思考,有一個根本的區別是什麼「這」是指當你處理值類型與引用類型。

當你在一個引用類型上調用「this」時 - 你得到的是一個生存在棧上的指針,你實際上並沒有得到這個對象本身。指針隱式地解除引用回堆中的對象,該對象抽象出間接性。現在,如果你是這樣說:此=新MyReferenceType(),你已經改變指針指向一個不同的堆對象在當前範圍 - 你有沒有改變原始對象本身在堆中,也不做任何其他引用/指針現在引用新的堆對象。它很有可能只要你的變異指針超出了範圍 - 你創建的新堆對象就會被垃圾收集。

當你在一個值類型上調用「this」時 - 你得到的是實際的對象,而不是一個引用或指針。沒有間接性,所以你可以自由地覆蓋這個內存位置的原始位(這正是默認構造函數的作用)。

1

只是一個猜測:

每類是存儲在堆中分配引用類型的意義和呼叫者通過指針得到實際數據的訪問。例如:

Customer c1 = new Customer('CUSTID'); // "Customer" is a reference type 
Customer c2 = c1; // "c1" and "c2" points to the same memory within the heap 

每個結構是該存儲器在堆棧中分配和呼叫方與實際的實例,而不是與參考該實例涉及一個值類型的含義。例如:

Customer c1 = new Customer('CUSTID'); // "Customer" is a value type 
Customer c2 = c1; // New memory gets allocated for "c2" within the stack 

考慮您的例子:在一個結構執行以下操作

this = new Customer(); 

簡單地用零個值初始化:

mov eax,dword ptr [ebp-3Ch] ; Save pointer to "ebp-3Ch" in EAX register 
xor edx,edx     ; Clear EDX register 
mov dword ptr [eax],edx  ; Write "zero" by address containing in EAX 

我不知道爲什麼它不可能與引用類型有關,但我的猜測是,將需要遍歷整個對象圖來完全「重置」它(這可能不是一件容易的事)。我認爲這將在循環引用的情況下變得有價值。

再一次,這只是我的想法,我非常想讓某人證明或放棄(當然有解釋)。