Exi*_*tos 1 c# stack ref-parameters
我正在阅读有关WCF和IDispatchMessageInspector的一些C#文档,并且该接口定义了一个通过引用传递的"Message"对象,以便可以对其进行操作.
当您通过ref传递某些东西而不是正常传递时,堆栈上实际发生了什么?
通过引用意味着您可以更改传递给项目的原始变量。它基本上传递堆栈上变量的地址而不是变量值。
正如您实际上询问堆栈上实际发生的情况一样,这里是按引用和按值方法的 IL 转储:
.method private hidebysig instance void ByRef(string& s) cil managed
{
// Code size 9 (0x9)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldstr "New value"
IL_0007: stind.ref
IL_0008: ret
} // end of method Class1::ByRef
Run Code Online (Sandbox Code Playgroud)
与
.method private hidebysig instance void ByValue(string s) cil managed
{
// Code size 9 (0x9)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "New value"
IL_0006: starg.s s
IL_0008: ret
} // end of method Class1::ByValue
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,主要区别在于参数类型(string&而不是string),并且它执行额外的步骤来间接加载和存储值。
简单的C#源码如下所示,供参考:
void ByRef(ref string s)
{
s = "New value";
}
void ByValue(string s)
{
s = "New value";
}
Run Code Online (Sandbox Code Playgroud)
它不是通过引用传递的对象 - 它是变量.
基本上,它将用作调用方参数的变量和您调用的方法中的参数别名:
public void Foo()
{
int x = 10;
Bar(ref x);
Console.WriteLine(x); // Prints 20
}
public void Bar(ref int y)
{
y = 20;
}
Run Code Online (Sandbox Code Playgroud)
在这里,x并y在本质上是相同的变量-它们指向同一个存储位置.所做的更改x是可见的y,反之亦然.(注意,在这种情况下,它是调用者中的局部变量,但它不一定是 - 如果您通过引用传递了一个实例变量,那么Bar可能会调用另一个更改同一变量的方法,然后y会被看到"神奇地"改变...)
有关C#中参数传递的更多信息,请参阅我关于该主题的文章.
| 归档时间: |
|
| 查看次数: |
172 次 |
| 最近记录: |