为什么我在一个函数中发送一个字符串作为参数它返回空?

Yan*_*hof 3 .net c#

使用此代码:

 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)

Jam*_*are 7

这不仅仅是字符串是不可变的,而且虽然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,或者你可以返回新的变异版本,或者存储在实例成员中(虽然按实例传递成员是一个更高的耦合顺序,并可能导致其他问题...).