Zac*_*son 14 .net c# out-parameters ref-parameters
当我对一个out或ref参数进行赋值时,是否会立即将值赋给调用者提供的引用,还是在方法返回时分配给引用的out和ref参数值?如果方法抛出异常,则返回值吗?
例如:
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?
}
Run Code Online (Sandbox Code Playgroud)
And*_*are 26
由于ref和out参数允许方法使用调用者传入的实际引用,因此在返回控件时,对这些引用的所有更改都会立即反映给调用者.
这意味着在上面的示例中(如果您要抓住ArgumentException当然),outValue并且refValue都将设置为2.
同样重要的是要注意out并且ref在IL级别上是相同的概念 - 只有C#编译器强制执行额外规则,out这要求方法在返回之前设置其值.因此,从CLR的角度来看outValue,它refValue具有相同的语义,并以相同的方式处理.
Eri*_*ert 14
安德鲁是对的; 我只会添加一些额外的细节.
首先,考虑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);
Run Code Online (Sandbox Code Playgroud)
在别名中,x,q和r都是相同的存储位置,因此打印20.在copy-in-copy-out引用中,这将打印10,x的最终值将取决于复制输出是否从左到右或从右到左.
最后,如果我没记错的话,在表达式树的实现中有一些罕见且奇怪的场景,我们实际上在ref参数上实现了copy-in-copy-out语义.我应该检查一下代码,看看我是否能记住这些场景到底是什么.
| 归档时间: |
|
| 查看次数: |
1517 次 |
| 最近记录: |