簡體   English   中英

什么時候C#'out'或'ref'參數的值實際返回給調用者?

[英]When is the value of a C# 'out' or 'ref' parameter actually returned to the caller?

當我對outref參數進行賦值時,是否會立即將值賦給調用者提供的引用,還是在方法返回時分配給引用的outref參數值? 如果方法拋出異常,則返回值嗎?

例如:

int callerOutValue = 1;
int callerRefValue = 1;
MyMethod(123456, out callerOutValue, ref callerRefValue);

bool MyMethod(int inValue, out int outValue, ref int refValue)
{
    outValue = 2;
    refValue = 2;

    throw new ArgumentException();

    // Is callerOutValue 1 or 2?
    // Is callerRefValue 1 or 2?
}

由於refout參數允許方法使用調用者傳入的實際引用,因此在返回控件時,對這些引用的所有更改都會立即反映給調用者。

這意味着在上面的示例中(如果您當然要捕獲ArgumentException ), outValuerefValue都將設置為2。

同樣重要的是要注意outref是IL級別的相同概念 - 只有C#編譯器強制執行out的額外規則,這要求方法在返回之前設置其值。 因此,從CLR的角度來看, outValuerefValue具有相同的語義並且以相同的方式處理。

安德魯是對的; 我只會添加一些額外的細節。

首先,考慮out / ref參數的正確方法是它們是變量的別名 也就是說,當你有一個方法M(ref int q)並將其稱為M(ref x)時,q和x是完全相同變量的兩個不同的名稱 變量是存儲位置; 你在q中存儲的東西,你也存儲在x中,因為它們是同一位置的兩個不同的名稱。

其次,您所描述的替代方案稱為“復制/復制”引用。 在這個方案中有兩個存儲位置,其中一個的內容在函數調用開始時被復制,並在完成時復制回來。 正如您所注意到的,copy-in-copy-out的語義與拋出異常時別名引用的語義不同。

在這樣奇怪的情況下,它們也有所不同:

void M(ref int q, ref int r)
{  
  q = 10;
  r = 20;
  print (q);
}

...

M(ref x, ref x);

在別名中,x,q和r都是相同的存儲位置,因此打印20.在copy-in-copy-out引用中,這將打印10,x的最終值將取決於復制輸出是否從左到右或從右到左。

最后,如果我沒記錯的話,在表達式樹的實現中有一些罕見且奇怪的場景,我們實際上在ref參數上實現了copy-in-copy-out語義。 我應該檢查一下代碼,看看我是否能記住這些場景到底是什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM