字符串的行为类似于值类型

Lia*_*ath 1 c# function value-type reference-type

我刚写了一个函数,我不明白为什么我得到的结果是:

private void ReplaceIfEmpty(string originalValue, string newValue)
{
  if (string.IsNullOrWhitespace(originalValue))
  {
    originalValue= newValue;
  }
}
Run Code Online (Sandbox Code Playgroud)

当我调用此函数时,原始值不会更新.我的理解是字符串是一个类,因此它是一个引用类型,因此我传入的值应该更新.你能解释一下为什么不是吗?

Jon*_*eet 19

这与参考类型和值类型无关.

您正在更改参数的值:

originalValue= newValue;
Run Code Online (Sandbox Code Playgroud)

对于没有refor或out修饰符的"普通"参数,该更改将永远不可见.

有关更多信息,请参阅我关于参数传递的文章,以及有关引用类型和值类型的文章,以确保您了解为什么有时它"看起来"像默认情况下通过引用传递引用类型.(它们不是:默认情况下所有参数都是按值传递的,只是对于引用类型,参数值是引用,而不是对象,因此对对象的更改仍然可以从调用者看到.)

所以你可以创建originalValue一个ref参数 - 但最好让方法返回一个参数string.我一般不愿意使用ref参数; 没有它们,代码通常更容易理解.


Eri*_*ert 7

您传递了对字符串引用.您没有传递对变量的引用.如果要更改变量,则执行以下操作:

private void ReplaceIfEmpty(ref string originalValue, string newValue)  ...
Run Code Online (Sandbox Code Playgroud)

差异往往让人困惑.这样想吧.想象两个房子,而不是想象一个字符串.现在想象两张纸上有那些房子的地址; 那些是房屋的引用.现在想象四个抽屉,每个抽屉都包含一张纸.抽屉标有p,q,x和y:

void M(House x, House y)
{
    x = y;
}
...
House p = new House("123 Sesame Street");
House q = new House("1600 Pennsylvania Avenue");
M(p, q);
Run Code Online (Sandbox Code Playgroud)

这个程序做什么用的?你在抽屉里放了一张纸说"123芝麻街".你在抽屉里放了一张纸说"宾夕法尼亚大道1600号".

您在抽屉p中复印纸张并将副本放入抽屉x中.您在抽屉q中制作纸张的复印件并将副本放入抽屉y中.然后你打电话给M.M制作了抽屉里的东西的复印件,并把它放在抽屉里. 抽屉p不受影响.

现在考虑这种情况:

void M(ref House r, House s)
{
    r = s;
}
...
House p = new House("123 Sesame Street");
House q = new House("1600 Pennsylvania Avenue");
M(ref p, q);
Run Code Online (Sandbox Code Playgroud)

这个程序做什么用的?你在抽屉里放了一张纸说"123芝麻街".你在抽屉里放了一张纸说"宾夕法尼亚大道1600号".

你在抽屉p上写了一个粘滞便笺,上面写着"这个抽屉也称为r".

您在抽屉q中复印纸张并将副本放入抽屉中.

然后你打电话给M.M制作了抽屉里的东西的复印件并把它放在抽屉里,这与抽屉p相同.

合理?


Bro*_*ass 5

您没有更改作为参数传递的变量的值originalValue,您正在尝试为其分配新实例,对于引用意味着该变量指向新引用 - 更新您需要传递字符串的引用 ref - 默认情况下引用是按值传递的,因此您传递的变量永远不会更新:

private void ReplaceIfEmpty(ref string originalValue, string newValue)
{
  if (string.IsNullOrWhitespace(originalValue))
  {
     originalValue = newValue;
  }
}
Run Code Online (Sandbox Code Playgroud)

一个更好的方法是返回新的字符串:

private string ReplaceIfEmpty(string originalValue, string newValue)
{
   if (string.IsNullOrWhitespace(originalValue))
      return newValue;
   else
      return originalValue;
}
Run Code Online (Sandbox Code Playgroud)

或者更方便使它成为一种扩展方法:

public static string ReplaceIfEmpty(this string originalValue, 
                                    string replaceValue)
{
   if (string.IsNullOrWhitespace(originalValue))
      return replaceValue;
   else
      return originalValue;
}
Run Code Online (Sandbox Code Playgroud)