C# 中的 ref 参数在堆栈上会发生什么?
我正在阅读一些有关 WCF 和 IDispatchMessageInspector 的 C# 文档,该接口定义了一个通过引用传递的“消息”对象,以便可以对其进行操作。
当您通过 ref 传递某些内容而不是正常传递时,堆栈上实际发生了什么?
Im reading some C# documentation about WCF and IDispatchMessageInspector and the interface defines a 'Message' object that is passed by reference so that it can be manipulated.
What actually happens on the stack when you pass something by ref as opposed to passing normally?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
通过引用传递的不是对象,而是变量。
基本上,它为调用方用作参数的变量以及您调用的方法中的参数别名:
这里,
x
和< code>y 本质上是相同的变量 - 它们引用相同的存储位置。对x
所做的更改可通过y
看到,反之亦然。 (请注意,在本例中,它是调用者中的局部变量,但不一定是 - 如果您通过引用传递了实例变量,则Bar
可能会调用另一个方法来更改同一变量,然后y
将被视为“神奇地”更改...)有关 C# 中参数传递的更多信息,请参阅我的 有关该主题的文章。
It's not the object that's passed by reference - it's the variable.
Basically it aliases the variable used as the argument from the calling side, and the parameter in the method that you call:
Here,
x
andy
are essentially the same variable - they refer to the same storage location. Changes made tox
are visible viay
and vice versa. (Note that in this case it's a local variable in the caller, but it doesn't have to be - if you'd passed an instance variable by reference, thenBar
might call another method which changes the same variable, and theny
would be seen to "magically" change...)For more about parameter passing in C#, refer to my article on the subject.
通过引用意味着您可以更改传递给项目的原始变量。它基本上传递堆栈上变量的地址而不是变量值。
IL 转储:
正如您实际询问堆栈上实际发生的情况,这里是按引用和按值方法的 IL 转储:
与
正如您所看到的,主要区别在于参数类型(
string&
而不是string
),并且它执行了额外的步骤来间接加载和存储值。简单的C#源码如下所示,供参考:
By reference means you can change the original variable passed to the item. It basically passes the address of the variable on the stack rather than the variable value.
IL Dump:
As you actually asked what actually happens on the stack here is an IL dump of a by ref and by value method:
vs.
As you can see the main difference is the parameter type (
string&
instead ofstring
) and that it does extra steps to load and store the values indirectly.The simple C# source is shown below for reference:
当你按价值传递某物时;在调用函数之前,会创建值类型的副本并将其放入堆栈中。当您通过引用传递某些内容时,该地址将被压入堆栈而不是创建副本,并且当您修改函数中的对象时,将修改原始对象而不是副本。
它的工作方式是,当编译器发现参数是通过 ref 传递时,会将您对变量的引用转换为间接内存访问。
例如,让我们假设在内存位置 100 有一个整数 123;现在,当您调用一个按值接受的函数(默认情况下)时,将在调用该函数之前制作 123 的副本并将其推送到堆栈上,这意味着该副本现在将位于(可以说)160 地址。但是,当您通过引用传递某些内容时,地址 100 将被推入堆栈并驻留在位置 160 上。
现在生成的指令将读取 160 以获取对象的位置,然后修改 100 处的数据。间接发生的情况与原样相同当您使用 * 运算符时,完成指针。
When you pass something by value; a copy of the value type is made and put on stack before the function is called. When you pass something by reference then the address of that is pushed on stack instead of creating a copy and when you modify the object in the function then the original object is being modified instead of the copy.
The way it works is that compiler translates your references to variable to indirect memory access when it sees that the argument was passed by ref.
For example let us assume at memory location 100 you have an integer 123; now when you call a function which accepts in by value (which is default) then copy of 123 will be made and pushed on stack before the function is called which means the copy will now be at (lets say) 160 address. However when you pass something by reference then address 100 will be pushed on stack and will reside on location 160.
Now the instructions generated will read 160 to get the location of object and then modify the data at 100. Indirection will happen same as it is done for pointers when you use * operator.
通过 ref 意味着您可以为传递的对象创建新实例,
按值不能仅更改对象属性
by ref means you can create new instance to the object passed,
by value cant do that just change the object properties