2011-10-05 27 views
2

我不能嘗試分辯了,但我敢肯定,有人知道:更改調用作用域的變量時,是否使用了參數?

MyType a; 
func(out a); 

會立即改變,一旦:

void func(out MyType A) { 
    A = new MyType(); 

    // do some other stuff here 

    // take some time ... and return 
} 

當我在異步方式一樣,調用此A在函數中分配了嗎?或者是僅當函數返回時纔將新對象引用分配給a?

如果我想在當前實施的行爲上轉播,是否有任何規範?

+0

更新我的答案根據您的要求,h – mtijn

回答

4

一旦在功能中分配了A,就會分配它。 out的使用爲您傳遞的任何內容提供了參考,這意味着只要它在方法中被修改,就會被修改。

從C#語言規範的提取物:

5.1.6輸出參數

用out修飾符聲明的參數是一個輸出參數。

輸出參數不會創建新的存儲位置。相反,輸出參數表示與作爲函數成員或委託調用中的參數給定的變量相同的存儲位置。因此,輸出參數的值總是與底層變量相同。

以下明確的分配規則適用於輸出參數。注意§5.1.5中描述的參考參數的不同規則。

·變量在作爲函數成員或委託調用中的輸出參數傳遞之前,無需明確賦值。

·在函數成員或委託調用正常完成之後,作爲輸出參數傳遞的每個變量都被視爲在該執行路徑中分配。

·在函數成員或匿名函數中,輸出參數首先被認爲是未分配的。

·函數成員或匿名函數的每個輸出參數必須在函數成員或匿名函數正常返回之前明確賦值(第5.3節)。

在結構類型的實例構造函數中,this關鍵字的行爲與結構類型(第7.6.7節)的輸出參數完全相同。

+0

您可以從這裏得到規範:http://msdn.microsoft.com/en-us/library/ms228593.aspx – Polynomial

+0

據我所知,唯一的證據是部分:「不創建新的存儲位置」。關於這些問題,所有其他文本都已經過時。謝謝! – user492238

3

只要線程超出,它就會被更改A = new MyType();

1

出來也被描述here而是一個短期和簡單的測試會告訴你你需要知道的速度不夠快是什麼:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 

namespace ConsoleApplication1 
{ 
class Program 
{ 
    static void TestOut(out int i) 
    { 
     i = 5; 
     Thread.Sleep(5000); 
    } 

    static void Main(string[] args) 
    { 
     int i = 1; 
     Console.WriteLine("i = " + i); 
     Thread testOut = new Thread(new ThreadStart(() => TestOut(out i))); 
     testOut.Start(); 
     Thread.Sleep(1000); 
     Console.WriteLine("i = " + i); 
     testOut.Join(); 
     Console.WriteLine("i = " + i); 

     Console.WriteLine("Press ENTER to exit"); 
     Console.ReadLine(); 
    } 
} 
} 

輸出:

I = 1

i = 5

i = 5

編輯:基於您的評論讓我補充如下: 在其他的答案中的一個聲明,但也包括在章節10.6 formal language specification documentation爲關鍵字out不限於章5.1.6。 1.3(p 307)如下:

10.6.1.3輸出參數 用out修飾符聲明的參數是輸出參數。與參考參數類似,輸出參數不會創建新的存儲位置。相反,輸出參數表示與方法調用中作爲參數給定的變量相同的存儲位置。

當形式參數是輸出參數時,方法調用中的相應參數必須包含關鍵字out,後跟一個與形式參數類型相同的變量引用(第5.3.3節)。變量在作爲輸出參數傳遞之前不需要明確賦值,但是在變量作爲輸出參數傳遞的調用之後,變量被認爲是明確賦值的。

在一個方法中,就像局部變量一樣,輸出參數最初被認爲是未分配的,必須在使用它的值之前明確賦值。

在方法返回之前,方法的每個輸出參數都必須明確賦值。

聲明爲部分方法(第10.2.7節)或迭代器(第10.14節)的方法不能具有輸出參數。

輸出參數通常用於產生多個返回值的方法中。例如:

using System; 

class Test 
{ 
    static void SplitPath(string path, out string dir, out string name) { 
     int i = path.Length; 
     while (i > 0) { 
      char ch = path[i – 1]; 
      if (ch == '\\' || ch == '/' || ch == ':') break; 
      i--; 
     } 
     dir = path.Substring(0, i); 
     name = path.Substring(i); 
    } 

    static void Main() { 
     string dir, name; 
     SplitPath("c:\\Windows\\System\\hello.txt", out dir, out name); 
     Console.WriteLine(dir); 
     Console.WriteLine(name); 
    } 
} 

此例產生輸出:

C:\ WINDOWS \ SYSTEM \ hello.txt的

注意dir和名稱變量可以是之前未分配他們被傳遞給SplitPath,並且他們在調用之後被認爲是明確分配的。

什麼必然是你的興趣是此款

引用參數相似,輸出參數不創建新的存儲位置。相反,輸出參數表示與方法調用中作爲參數給定的變量相同的存儲位置。

其中明確指出參數沒有自己的存儲位置,因此改變它在函數中的值會改變原來的值。

+0

+1進行測試。但是一個規範參考將高度讚賞。鏈接僅轉到手動描述。它不處理這個問題。 – user492238

+0

你的願望是我的命令,我相應地更新了答案,擴展了現有的答案之一 – mtijn

0

Here是關於ref和線程安全性的問題,其結論是它不是線程安全的。 out與ref幾乎相同(out支持null引用),並且它不是線程安全的,這意味着值會立即更改。

相關問題