繁体   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