2016-08-03 32 views
2

我很難理解C#中ref關鍵字的作用。 在我的C++代碼中,我創建了一個字符串變量以及指向它的指針和引用變量。我將它傳遞給Delete或Change函數,並且如預期的那樣,所有3個變量都被修改。C#通過引用(ref關鍵字)問題

但是,用C#創建變量x並使用字符串數據初始化變量。我正在創建一個變量y,應該引用x。然後,我將xref關鍵字一起傳遞給ChangeDelete方法,從而導致方法內部的變量以及x被修改。但是,y未被修改,即使它應該是對x的引用,就像在C++中一樣。這不僅僅是一個字符串問題,因爲我已經用C#對象嘗試了上述測試,並得到了相同的結果。

這是否意味着y複製x當我執行var y = x

C++

#include <iostream> 
using namespace std; 

void Delete(string &variable) 
{ 
    variable = ""; 
} 

void Change(string &variable) 
{ 
    variable = "changed data"; 
} 

void main() 
{ 
    string x = "data"; 
    string *y = &x; 
    string &z = x; 
    Delete(x); 
} 

C#

namespace ConsoleApplication1 
{ 
    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      var x = "data"; 
      var y = x; 
      Change(ref x); 
     } 


     public static void Delete(ref string variable) 
     { 
      variable = null; 
     } 

     public static void Change(ref string variable) 
     { 
      variable = "changed"; 
     } 
    } 
} 
+0

@mash:在該示例中,LHS被改變 - 在這個例子中,RHS被改變。 –

+0

問題不在於'ref'關鍵字 - 問題是當x更改時,y不會更新x的值。 –

+0

也考慮在C#中使用'out'關鍵字而不是'ref'(請參閱:http://stackoverflow.com/questions/1516876/when-to-use-ref-vs-out) – Sal

回答

2

這條線: VAR Y = X; 使y成爲x的副本,而不是對c中的x的引用# 因此,當您調用Changed函數時不會改變它。

似乎沒有一種簡單的方法可以在C#(或大多數其他語言)中重現相同的C++行爲。

當您將非值類型對象作爲參數傳遞給函數時,該對象是通過值傳遞的,但對象內容(屬性/字段等)是通過引用傳遞的(您可以從函數),當你用「ref」關鍵字傳遞對象時,對象本身是byref並且也可以被改變,(它與發送指針相同,或者在C++中發送一個雙指針給結構體(它本身就是指針) /C)。

+0

如果'y'成爲'x'的副本,那麼如果'x'是一個名爲'Value'的字符串屬性的對象,並且該對象被傳遞給了不帶'ref'關鍵字的函數,那麼怎麼辦?該函數修改了「Value」屬性。爲什麼後來修改'x'和'y'的'Value'屬性?如果'y'被價值複製了,那麼它會不知道對'x'所做的更改? – Sharpiro

+1

@Sharpiro:如果沒有'ref',仍然允許對對象內部狀態的更改 - 在方法調用後只有對象標識不變。換句話說,(沒有'ref')對象保證保持相同的對象,但狀態可以被修改。 –

+0

我編輯了我的答案.. –

0

問題的核心是字符串是在C#中被視爲值類型(基元),但在C++中被視爲引用類型。因此,將字符串分配給另一個變量將簡單複製Dr.Haimovitz寫的值。

您可以通過編寫「非安全代碼」來訪問C#中變量的實際指針。 https://msdn.microsoft.com/en-us/library/aa288474(v=vs.71).aspx

+0

我很肯定這是錯誤的。我相信字符串是具有價值行爲的引用類型。 http://stackoverflow.com/questions/636932/in-c-why-is-string-a-reference-type-that-behaves-like-a-value-type – Sharpiro

+0

更正了我的答案,以上更準確。 – Sal

1

除了'不安全'的代碼,沒有辦法在C#中重現這種行爲。 即使第二個變量的標識發生變化,C++也有能力使指針保持固定到另一個變量,但在大多數其他語言中,該C++功能根本不可用。

這不是字符串或任何其他類型的特殊功能。 例如,在下面的C的端部++代碼,「G」點到更新的「F」,其被設置爲「SomeOtherFoo」:

Foo f; 
Foo *g = &f; 
f = SomeOtherFoo(); 
//'g' points to the updated 'f' 

在「安全」 C#,在所述端部下面的代碼,「G」仍然是原來的對象,而不是由「SomeOtherFoo」返回的新的:

Foo f = new Foo(); 
Foo g = f; 
f = SomeOtherFoo(); 
//'g' does not point to the updated 'f'