当引用变量可以通过引用传递时:
class Example
{
public string str="Demo";
public int[] intValues={1,3,4,5};
public static void StrPassing(string someStr)
{
string otherStr="Changed!";
someStr=otherStr;
}
public static void NumPassing(int[] a)
{
a[2] = 115;
}
}
static void Main(string[] args)
{
Example ex = new Example();
Example.StrPassing(ex.str);
Example.NumPassing(ex.intValues);
foreach (int i in ex.intValues)
{
Console.WriteLine(i);
}
Console.WriteLine(ex.str);
Console.ReadLine();
}
intValues[2]
的值在传递引用时更改为115
。但字符串“str”(demo)的值不会更改为“已更改!”。什么是它的原因?。我可以把它作为数组通过引用传递,其他引用类型传递
值?
答案 0 :(得分:5)
无论传递给方法的是什么,因为参数是通过值传递的,对于引用类型,这意味着引用是按值传递的。因此,您无法将对象更改为另一个,但您可以确定地更改其内容(因为这不会更改实际引用,只会更改其他地方的内存)。< / p>
正如您在数组中的示例所示,您将获取数组引用(但不要更改它)并更改数组中的值。这就像获取一些对象并更改属性值一样。你也可以在一种方法中做到这一点。 如果要更改字符串(.NET中的不可变对象),则需要使用 并称之为: 回到您的阵列:您也很难将传递的数组更改为完全不同的数组: 也不会起作用,因为然后你会尝试将字符串更改为完全不同的字符串。ref
参数:public static void StrPassing(ref string someStr)
{
string otherStr="Changed!";
someStr=otherStr;
}
string foo = "foo";
StrPassing(ref foo);
Console.WriteLine(foo); // should print "Changed!"
ref
关键字确保您的方法获得对字符串的实际引用并可以更改它,而不仅仅是引用的副本。那么你可以用一个全新的替换对象。public static void NumPassing(int[] a)
{
a = new int[15];
}
答案 1 :(得分:3)
您需要区分更改变量引用的对象和更改*对象的内容“。
在此代码中:
public static void StrPassing(string someStr)
{
string otherStr="Changed!";
someStr=otherStr;
}
...您正在更改someStr
的值。您没有对someStr
最初引用的字符串进行任何更改。实际上,你不能因为字符串是不可变的。 (如果是StringBuilder
,您可以将长度设置为0然后追加“已更改!”。
更改someStr
的值无效,因为参数(ex.str
)是按值传递的。 (有问题的值是引用,但这并不意味着它通过引用传递。)
现在将其与此代码进行比较:
public static void NumPassing(int[] a)
{
a[2] = 115;
}
此处您不更改a
的值 - 您正在更改a
引用的数组的内容。
简而言之,除非您使用ref
/ out
,否则参数将按值传递 - 但对于引用类型,该值只是一个引用。
我有一个article on parameter passing,可以更详细地介绍所有这些内容。
答案 2 :(得分:1)
您需要做的是将StrPassing
的签名更改为:
public static void StrPassing(ref string someStr)
答案 3 :(得分:0)
字符串在C#中是特殊的。它们是不可变的引用类型,使它们表现出与值类型类似的行为。
Here's一个很好的讨论。