使用此代码:
void SomeMethod(string str)
{
string tmpStr = ... Read some value from file ...
if( !tmpStr.Empty() )
str = tmpStr;
}
Run Code Online (Sandbox Code Playgroud)
当我使用刚在主子例程中创建的简单字符串调用此方法时:
string localString = "";
SomeMethod( localString );
Run Code Online (Sandbox Code Playgroud)
localString当我在调试中看到SomeMethod变量tmpStr不为空且方法中的变量str充满了chars 时,我重新获得的值是一个空事件.
如果我将SomeMethod签名更改为:
SomeMethod(ref string str)
Run Code Online (Sandbox Code Playgroud)
我看到了正确的结果.
但是string是一个引用类型,所以为什么我需要在这种情况下发送它ref?为什么我得到的结果是我预期的,只有在我打电话时:
SomeMethod(string str)
Run Code Online (Sandbox Code Playgroud)
这不仅仅是字符串是不可变的,而且虽然string是引用类型,但引用本身却不是.也就是说,您传递的string是引用,但引用本身是按值传递的.
因此,对于引用类型,您可以修改参数引用的对象(只要它是可修改的),但除非通过引用传递参数,否则无法修改参数引用的内容.
因此,当您尝试更改string变量引用的内容时:
str = tmpStr;
Run Code Online (Sandbox Code Playgroud)
它改变了str本地引用的内容,但不影响原始参数localString引用的内容.
可以这样想,假设参数localString引用位置1000处的对象:
localString
+---------------+ 1000
| 1000 | -----------------> +---------------+
+---------------+ | Count: 1 |
| Value: "" |
+---------------+
Run Code Online (Sandbox Code Playgroud)
然后,当我们传递localString给方法时,它会创建引用的副本(as str)并更新引用计数...
localString
+---------------+ 1000
| 1000 | -----------------> +---------------+
+---------------+ | Count: 2 |
| Value: "" |
str +---------------+
+---------------+ ^
| 1000 | ---------------------+
+---------------+
Run Code Online (Sandbox Code Playgroud)
然后,当您将str分配给新字符串时,它会修改引用str但不会localString:
localString
+---------------+ 1000
| 1000 | -----------------> +---------------+
+---------------+ | Count: 1 |
| Value: "" |
str +---------------+
+---------------+ 2500
| 2500 | ---------------------> +---------------+
+---------------+ | Count: 1 |
| Value: ... |
+---------------+
Run Code Online (Sandbox Code Playgroud)
所以你的修改str只改变了str所指的内容,而不是原始的引用localString,如果你想改变它,那么你通过引用传递,这意味着它str是一个回到原始参数的引用(很像ptr到ptr):
localString
+---------------+ 1000
| 2500 | ------------------> +---------------+
+---------------+ | Count: 2 |
^ | Value: "" |
str | +---------------+
+---------------+
| |
+---------------+
Run Code Online (Sandbox Code Playgroud)
现在,当你改变str它时也改变了引用localString:
localString
+---------------+ 1000
| 1000 | -----+ +---------------+
+---------------+ | | Count: 0 |
^ | | Value: "" |
str | | +---------------+
+---------------+ | 2500
| | +----------------> +---------------+
+---------------+ | Count: 1 |
| Value: ... |
+---------------+
Run Code Online (Sandbox Code Playgroud)
然后,当然,原始字符串(假设在此示例中没有其他任何引用它)可以被垃圾收集...
所以,如果你真的想要修改string参数,通过ref或传递它out,或者你可以返回新的变异版本,或者存储在实例成员中(虽然按实例传递成员是一个更高的耦合顺序,并可能导致其他问题...).
| 归档时间: |
|
| 查看次数: |
132 次 |
| 最近记录: |