2012-03-16 231 views
3

注:我的問題有幾個部分。如果您願意回答每個問題,我將不勝感激,而不僅僅是告訴我該怎麼做才能編譯。 :)這個C#結構有什麼問題?

我不以任何方式與C#良好。事實上,我不太瞭解它的原因是我的課程專注於製作高效的算法,而不是真正教授我們.NET。儘管如此,我們所有的程序都必須使用.NET編寫,直到現在纔出現問題。我有下面的代碼,但它不會編譯,我不明白爲什麼。我有一種直覺,認爲這應該完全重寫,但在我這樣做之前,我想知道爲什麼這是不允許的。

該結構的問題是相反的順序,並隨後建立鏈表狀結構,所以我可以添加另一節點的「列表」的結尾,然後遍歷和召回節點

private struct BackPointer 
{ 
    public BackPointer previous; 
    public string a; 
    public string b; 
    public BackPointer(BackPointer p, string aa, string bb) 
    { 
     previous = p; 
     a = aa; 
     b = bb; 
    } 
} 

然後在我的代碼,我有話要的

BackPointer pointer = new BackPointer(); 
pointer = new BackPointer(pointer, somestring_a, somestring_b); 

效果我得到的編譯錯誤是Struct member 'MyClass.BackPointer.previous' of type 'MyClass.BackPointer' causes a cycle in the struct layout

這似乎是一個明顯的錯誤。它不喜歡我在同一個結構的構造函數中傳入結構的事實。但爲什麼是不允許的?我想這個代碼會在列表中創建一個新節點,並返回一個指向上一個節點的指針,但顯然這不會發生。那麼會發生什麼呢?最後,解決這個問題的建議方法是什麼?我只是想告訴它是非託管的,只是手動處理我的指針,但我真的知道如何在C++中實現這一點。我真的不知道C#中會出現什麼問題。

+2

在C#中,與C++不同,'struct's和'class'es是非常不同的。 – SLaks 2012-03-16 16:47:17

+0

類似的問題在這裏討論 http://stackoverflow.com/questions/651552/cannibal-classes – amdmax 2012-03-16 16:52:27

+0

哦哇!我不知道它們與C++結構體非常不同。這很有道理,爲什麼你不能這樣做。我不得不選擇我認爲是最好的答案,並回答了實際問題。但是,我確實收到了所有幫助我更多瞭解該主題的答案。謝謝! – Bob 2012-03-16 17:04:47

回答

6

但爲什麼不允許?

它是一個結構 - 一個值類型。這意味着無論你有哪種類型的變量,該變量都包含結構中的所有字段,直接內聯。如果某個東西包含了它自己(或者創建了一個更復雜的循環),那麼你顯然不能爲它分配足夠的空間 - 因爲它必須有足夠的空間來存儲它的所有字段和它自己的另一個副本

最後是什麼建議解決這個問題的方法?

寫一個類而不是結構體。那麼變量的值將是一個參考到一個實例,而不是數據本身。這就是你如何得到關閉到C#中的「指針」。 (指針和引用是不同的,你要知道。)

我建議你閱讀我的文章value types and reference types更多信息 - 這是一個絕對關鍵話題在C#中瞭解。

10

這不是指針;這是一個實際嵌入的struct值。
struct的整點是他們(幾乎)從不指針。

您應該改用class

+0

等等,什麼? (幾乎)從來沒有一個指針?這是否意味着有一個角落的情況下,C#會將一個結構作爲指針? – Bob 2012-03-16 17:06:12

+0

@Bob:'ref'參數,盒裝結構體,'this'等實例方法。 – SLaks 2012-03-16 17:06:41

3

在創建反向指針之前,反向指針必須存在,因爲如果沒有另一個反向指針(這將需要另一個反向指針並且繼續),則不能有反向指針。你根本不能根據你創建的方式創建一個Backpointer,因爲作爲一個結構,Backpointer永遠不能爲空。

換句話說,用這段代碼創建一個Backpointer是不可能的。編譯器知道這一點,所以它迫使你做出邏輯上合理的事情。

0

結構按值存儲。在這種情況下,你的結構體內存儲了同一個結構體的另一個實例。該結構體內存儲另一個結構體等。因此這是不可能的。這就像是說世界上每個人都有一個孩子。這是不可能的。

你需要使用的是一個類。類通過引用存儲,這意味着它不會將類存儲在它自己內部,它只存儲對該類的引用。

0

CLR struct定義爲value type。這意味着你的上下文是編譯器需要知道類型的確切佈局。但是,它無法知道如何佈置包含自身實例的類型 - 這聽起來合理嗎?將結構更改爲類(這會使您的BackPointerreference type),並且您會發現它可以開箱即用。原因是任何引用類型的實例總是具有相同的佈局 - 它基本上只是一個指向託管堆的某個位置的「指針」。我強烈建議閱讀一些關於C#或CLI類型系統的基礎知識。