2011-09-19 75 views
1

以下兩個代碼片段有什麼區別?C#輸出參數

public void foo(out classA x) 
{ 
    y = new classA(); 
    x = y; 
} 

與第二:

public void foo(out classA x) 
{ 
    classA y; 
    x = y; 
} 

這是真的,第二個片段是危險的,因爲x現在有一個參考這個地方y,退出foo後,這可能是已經死了嗎?

爲什麼我們一般使用「新」?

我有點困惑,因爲在C++中,如果x在第二個片段將是一個指針,語句x = y甚至不會因爲y編譯不是指針。

+11

它們都沒有編譯。 –

+1

第二個是不危險的。這是沒用的,因爲你永遠不會爲y賦值。 – JohnFx

+1

在C#中,類總是分配在堆上,所以你不必擔心。 – Gabe

回答

2

你的混亂,我想是,在C++第二示例將返回一個參照本發明的堆棧分配的對象。這在C#中不會發生。

鑑於C#你的第二個例子:

public void foo(out classA x) 
{ 
    classA y; // Doesn't allocate an object 
    x = y; 
} 

這可能不會編譯,無論如何,因爲y從未賦值。

4

讓我們假設一下,如果第二個片段是

public void foo(out classA x) 
{ 
    classA y = new classA(); 
    x = y; 
} 

的片斷,你寫它不C#編譯的。必須先分配y。行classA y;不會像在C++中那樣在堆棧上創建classA的實例。它只是聲明classA類型的變量y

考慮到的編譯代碼段,分配一個out變量本地聲明和初始化對象是不以任何方式危險。該classA對象y點,並分配給x仍然活得很好,直到x超出無論它的聲明/使用範圍。

+1

我想補充一點,.NET使用引用計數來跟蹤所創建的實例,所以不像C++,你在本地創建實例會當它超出範圍去分配的'實例上面確實y'沒有超出範圍,而是在函數退出時將一個引用添加到「正在使用」計數(x)中,然後減去一個引用(y)。當其「正在使用」計數下降到0時,垃圾收集器就會出現並實際從內存中移除它。在哪一刻它已經消失了。 – CodingGorilla

+2

@CodingGorilla .NET CLR不使用引用計數。垃圾收集器遍歷對象樹並跟蹤運行代碼不再可訪問的引用。 –

+1

你是對的,我試圖解釋這個觀點,即只要它在使用中,這個實例就一直存在於內存中,並且這是一個不好的方法來解釋它(特別是因爲引用計數是一種完全不同的技術),但希望我們兩個人之間他得到了這個想法。 – CodingGorilla

1

這是真的,第二個片段是危險[...]

不是在C#;你正在考慮像C或C++這樣的本地語言,它允許我們將一個指針指向一個局部變量。在C#中,所有內容(在合理範圍內)都是對託管對象的引用。一切都基本上在堆上。

1

這是不危險的,因爲代碼將無法被編譯,除非所有的「出」參數給出的方法返回或退出之前的定義。