2017-04-07 19 views
2

我目前正在努力理解什麼時,它說,與「出」的關鍵字,我們能夠多個值這個意思。例如從msdn站點(https://msdn.microsoft.com/en-us/library/ee332485.aspx):「...下面的示例使用到返回三個變量與一個單一的方法調用。」返回與多值的「出」關鍵字在C#

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; 
    } 
} 

我不知道如果我只是沒有閱讀說明書的權利,但它似乎是()方法實際上並不返回(不使用「回」關鍵字)任何東西所有和基本上分配領域(類似地通過由ref傳遞)。這與其他消息來源一致,他們聲稱使用'出'可以返回多個值。我是否誤解了返回詞的上下文,還是我沒有正確理解這個概念?

+1

'out'關鍵字意味着在方法調用之後,這些變量必須分配一些東西。 – dcg

+2

它在語義上等同於返回。你調用一個方法,並且你的「out」變量充滿了結果,就像當你調用一個返回類型的方法並且有一個變量充滿了結果一樣。 – Evk

+1

'out'關鍵字意味着外部範圍中的所有值將被「創建」和「分配」。你可以說他們已經被返回,因爲'out'聲明瞭合約,這些值必須在當前的mehtod中改變。 –

回答

6

該方法確實沒有返回值,正如您正確注意到的那樣。 refout都與參考一起使用。

ref將讓編譯器知道該變量在進入函數之前應該已經被初始化(當在該函數之前使用該變量並且現在想改變某些時,這是有用的)。 out將讓編譯器知道該對象在它正在調用的函數內被初始化。所以ref兩種方式,out是外置的。

所以,是的,它實際上並沒有返回任何東西。但另一方面,它會將值分配給您的變量,通過這些變量您的調用方法也會以新值結束。基本上你可以看到這是一個回報。

因此,在短期:

  • ref參數 - 這些具有相同的功能,C++參考 參數,和

  • out參數 - 這些允許從一個方法傳遞迴數據,但不 進入方法。

我也建議你閱讀this SO answer和喬恩斯基特的有關參數傳遞的corresponding blog。它會給你很多關於這個概念的信息。而作爲喬恩斯基特音符,用refout時一定要小心:

它基本上得到另一個返回值的一種方式,並應 通常精確地避免,因爲這意味着該方法的可能 試圖做太多。

+2

@xanatos爲了使它更加清晰,我重新編寫了它。感謝您指出! – Jurjen

3

它使用術語return作爲其語義含義,而不是將其用作關鍵字。

語義,當您使用out關鍵字,您指定兩件事情:

  1. 參數不用於輸入。
  2. 該參數的值將在方法返回前明確賦值。

在這方面,out參數是從該方法返回的值。

編譯器強制執行這些語義。下面的代碼會產生一些警告:

public static void Test(out int x) 
{ 
    Console.WriteLine(x); 
} 

錯誤CS0177的輸出參數「X」必須被分配到控制離開當前方法

未分配的輸出參數「x的錯誤CS0269使用前'

請注意,C#7(又名Visual Studio 2017)將允許您在方法調用中聲明變量。

考慮:

public static void Test(out int x, out int y) 
{ 
    x = 1; 
    y = 2; 
} 

C#7,您可以這樣做:

Test(out int x, out int y); 
Console.WriteLine($"x = {x}, y = {y}"); 

這句法使得它更明顯的是,一些被「退回」,自變量被聲明和初始化同樣的聲明。

另外在C#7中,您可以使用元組而不是out,我認爲它更好(並且對lambda表達式有更好的效果!)。

上面的例子可以在C#中被重寫如下7:

public static (int x, int y) Test() 
{ 
    int x = 1; 
    int y = 2; 
    return (x, y); 
} 

然後,你可以這樣做:

(int x, int y) = Test(); 
Console.WriteLine($"x = {x}, y = {y}"); 
3

你說得對,該方法只能回報(就你所說的而言)最多隻有一件事。或者,根據您的聲明(返回類型void),當方法完成時,它根本不會返回任何內容給調用代碼。

如果你想從你的方法獲取多個值回來了,你有兩個選擇:

  1. 返回classstruct - 那是一回事,但它可以包含多個值(屬性那東西)

  2. 根據您的示例,將一些參數傳入帶out修飾符的方法中。 out類似於ref,因爲您的方法正在處理實際值而不是其副本。但與ref不同,該方法必須在方法完成之前爲標記爲out的任何參數分配值(否則將發生編譯器錯誤)。你可以有多個參數,其上有out修飾符。

所以,這取決於你的意思是什麼了一下。在返回值的意義上,您的示例代碼不返回任何內容(它的返回類型爲void),如果您將其更改爲返回類型,則最多隻能返回一個返回值。但是在告訴調用代碼關於該方法內部完成了什麼的意義上,使用out參數可以爲多個值執行此操作。