我刚写了一个函数,我不明白为什么我得到的结果是:
private void ReplaceIfEmpty(string originalValue, string newValue)
{
if (string.IsNullOrWhitespace(originalValue))
{
originalValue= newValue;
}
}
当我调用此函数时,原始值不会更新。我的理解是字符串是一个类,因此它是一个引用类型,因此我传入的值应该更新。你能解释一下为什么不是吗?
答案 0 :(得分:19)
这与参考类型与值类型无关。
您正在更改参数的值:
originalValue= newValue;
对于没有ref
或out
修饰符的“普通”参数,该更改永远不会可见。
请参阅我的article on parameter passing以获取更多信息,以及我在reference types and value types上的文章,以确保您了解为什么有时“看起来”类似于默认情况下通过引用传递引用类型。 (它们不是:默认情况下所有参数都是按值传递的,只是对于引用类型,参数值是引用,而不是对象,因此对对象的更改仍然是可见的来电者。)
所以可以使originalValue
成为ref
参数 - 但最好让方法返回string
。我一般不愿意使用ref
参数;没有它们,代码通常更容易理解。
答案 1 :(得分:7)
您将引用传递给字符串。您没有传递对变量的引用。如果您想更改变量,那么您可以这样做:
private void ReplaceIfEmpty(ref string originalValue, string newValue) ...
这种差异经常让人感到困惑。这样想吧。想象两个房子,而不是想象一个字符串。现在想象两张纸上有那些房子的地址;这些是引用到房子。现在想象四个抽屉,每个抽屉都包含一张纸。抽屉标记为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);
这个程序做什么?你把一张纸说成芝麻街" 123芝麻街"在抽屉里。你把一张纸说成宾夕法尼亚大道" 1600宾夕法尼亚大道"在抽屉q。
您在纸盒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);
这个程序做什么?你把一张纸说成芝麻街" 123芝麻街"在抽屉里。你把一张纸说成宾夕法尼亚大道" 1600宾夕法尼亚大道"在抽屉q。
你在抽屉p上贴上了一张粘滞便笺,上面写着"这个抽屉也被称为r"。
您在纸盒q中复印纸张并将副本放入纸盒中。
然后你打电话给M.M复印抽屉里的东西并把它放在抽屉里,和抽屉p 相同。
有意义吗?
答案 2 :(得分:5)
您没有更改作为参数originalValue
传递的变量的值,您正在尝试为其分配一个新实例,这对于引用意味着该变量指向一个新引用 - 更新一个 reference 您需要通过ref传递字符串 - 默认情况下,引用按值传递,因此您传递的变量永远不会更新:
private void ReplaceIfEmpty(ref string originalValue, string newValue)
{
if (string.IsNullOrWhitespace(originalValue))
{
originalValue = newValue;
}
}
更好的方法是返回新字符串:
private string ReplaceIfEmpty(string originalValue, string newValue)
{
if (string.IsNullOrWhitespace(originalValue))
return newValue;
else
return originalValue;
}
或者更方便使它成为一种扩展方法:
public static string ReplaceIfEmpty(this string originalValue,
string replaceValue)
{
if (string.IsNullOrWhitespace(originalValue))
return replaceValue;
else
return originalValue;
}
答案 3 :(得分:0)
当您执行以下任务时:
originalValue = newValue;
您没有更改originalValue
引用的字符串值,而是将originalValue
的值更改为指向与newValue
相同的位置。
字符串是不可变的,在设置后无法修改,只能重新分配。