2012-08-31 63 views
3

可能重複:
C# - Reference type still needs pass by ref?'出' 修飾符

class OutReturnExample 
{ 
    static void Method(out int i, out string s1, out string s2) 
    { 
     i = 44; 
     s1 = "I've been returned"; 
     s2 = null; 
    } 
    static void Main() 
    { 
     int value; 
     string str1, str2; 
     Method(out value, out str1, out str2); 
     // value is now 44 
     // str1 is now "I've been returned" 
     // str2 is (still) null; 
    } 

我是新來的C#和學習了修改。我碰到this snippet on MSDN

我知道out在這裏對於int原始變量很有用,但對於字符串變量,即使沒有out修飾符,引用也會傳遞給被調用的方法,對吧?

+1

不,不對。如果字符串參數未標記爲out,則s1和s2將被視爲局部變量。不要在參考文獻本身,而是參考參考文獻時考慮ref和out。 –

+1

對於引用類型(例如字符串),引用將按值傳遞。這意味着您可以更改實例的內容,但不能更改引用本身。在字符串的情況下,你甚至不能更改內容,因爲它們是不可變的。 – CodesInChaos

回答

9

即使沒有out修飾符,引用也會傳遞給被調用的方法,對吧?

是的,但沒有out他們不會被傳遞迴:

void M(string s1, out string s2) 
{ 
    s1 = "one"; 
    s2 = "two"; 
} 

void Main() 
{ 
    string s = "hello", t = "world"; 
    // s = "hello" 
    // t = "world" 
    M(s, out t); 
    // s = "hello" 
    // t = "two" 
} 

string設計爲不可變的。你可能會想可變引用類型:

class Person { public string Name { get; set; } } 

void Main() 
{ 
    var p = new Person { Name = "Homer" }; 
    // p != null 
    // p.Name = "Homer" 
    M2(p); 
    // p != null 
    // p.Name = "Bart" 
} 

void M2(Person q) 
{ 
    q.Name = "Bart"; // q references same object as p 
    q = null;   // no effect, q is a copy of p 
} 
+1

+1。我soooo slooooowwwww拿出完全相同的答案:) –

0

您是需要從方法返回之前設置out parameters。所以傳入的內容並不重要,因爲它可以被覆蓋。

雖然作爲out參數傳遞的變量在傳遞之前不必被初始化,但被調用的方法需要在方法返回之前分配一個值。

3

但是對於字符串變量,即使沒有修飾符,引用也會傳遞給被調用的方法,對嗎?

是的,但你不能改變參考本身。當您在方法內設置s1 = "I've been returned";時,您正在爲s1變量分配一個新的字符串實例。變量本身是通過值傳遞的,所以調用函數看不到這個賦值。

這是更清楚,如果你有一個類:

class Foo 
{ 
    public string Value { get; set; } 
} 

如果傳遞到這個方法沒有ref或out,你仍然可以看到的變化裏面的實例,因爲它是通過基準:

static void Method(Foo foo) 
{ 
    foo.Value = "Bar"; 
} 

有了這個,你可以撥打:

Foo foo = new Foo { Value = "Foo" }; 
Method(foo); 
Console.WriteLine(foo.Value); // Prints Bar 

但是,如果將值設置爲不同的實例:

static void Method2(Foo foo) 
{ 
    foo = new Foo {Value = "Bar" }; 
} 

這將不會顯示:

​​

通過用ref或out路過,你讓變量本身被重新分配:

static void Method3(ref Foo foo) 
{ 
    foo = new Foo {Value = "Bar" }; 
} 


Foo foo = new Foo { Value = "Foo" }; 
Method3(ref foo); // This will change what foo references now 
Console.WriteLine(foo.Value); // Prints Bar again 
3

這是區別:如果它不是out那麼調用者中的值不會更新。

static void Method(string s1, out string s2) 
{ 
    s1 = "I've been returned"; 
    s2 = "changed!!!"; 
} 

static void Main() 
{ 
    string str1 = "one"; 
    string str2 "two"; 
    Method(str1, out str2); 
    // str1 is still "one" 
    // str2 is "changed!"; 
} 

注意null爲您的樣品中str2實際上是從法的到來。你只是看不到差異,因爲在呼叫之後之前爲空。

0

這對你的主要問題有點偏離主題,但我認爲這可能會幫助你更好地理解out修飾符的用途。

out參數被認爲是在像Int32.TryParse(String value, out int i),讓你可以寫不必手動處理常見的異常,例如代碼方法的其他有用的模式,

int i; 
if (Int32.TryParse("blah", out i)) 
{ 
    Console.WriteLine("Valid Integer"); 
} 
else 
{ 
    Console.WriteLine("Invalid input"); 
} 

這是一個簡單的例子,但這是一種相當常見且有用的模式,可以嘗試執行某些操作並返回它是否成功並返回結果值。

的這在.NET另一個更廣泛的應用的例子是在一個字典中的TryGetValue()方法 - 見Dictionary.TryGetValue Method (TKey, TValue)(MSDN)。