考虑以下方法:
static void ChangeArray(params string[] array) {
for (int i = 0; i < array.Length; i++)
array[i] = array[i] + "s";
}
如果我将其称为传递字符串数组,则此方法有效:
string[] array = {"Michael", "Jordan"} // will become {"Michaels", "Jordans"}
ChangeArray(array);
但是如果我使用字符串参数调用它将无法工作:
string Michael = "Michael";
string Jordan = "Jordan";
ChangeArray(Michael, Jordan); // This will NOT change the values of the variables
据我所知,编译器会将Michael和Jordan包装在一个数组上,所以两种情况下结果不一样吗?
答案 0 :(得分:23)
你的第二个例子基本上是:
string Michael = "Michael";
string Jordan = "Jordan";
{
var tmp = new string[] {Michael, Jordan};
ChangeArray(tmp);
}
如此;实际上,tmp
中的值已经更改了......但之后丢弃了tmp
,因此您没有看到任何内容。 params
不模仿ref
- 它不会按位置更新回原始变量。或者在代码中,不以下内容:
string Michael = "Michael";
string Jordan = "Jordan";
{
var tmp = new string[] {Michael, Jordan};
ChangeArray(tmp);
Michael = tmp[0];
Jordan = tmp[1];
}
如果您需要它的行为,那么代码就像那样 - 或者使用带有ref
参数的重载。
答案 1 :(得分:5)
原因是string
是一个不可变类型 - 你传入包含在数组中的string
个实例。该数组现在包含两个新字符串(具有与原始字符串相同但不同实例的值)。更改阵列时,这些副本将被丢弃,阵列插槽将保留一个新字符串。当函数返回时,临时数组将被丢弃。因此,您的原始输入字符串永远不会被修改(它们无论如何都不可能,因为string
是 - 再次 - 不可变的。)
编辑我在评论中提到Lee的论点之后对这个答案进行了编辑(我将保留答案,只是为了完成以下讨论)。不可变部分确实与问题无关。主要的根本问题是对被丢弃的临时数组进行了更改。
答案 2 :(得分:2)
这很奇怪(我不知道这一点),但是as specified。
参数数组允许在方法调用中以两种方式之一指定参数:
为参数数组提供的参数可以是可隐式转换(第6.1节)到参数数组类型的类型的单个表达式。在这种情况下,参数数组的作用就像一个值参数。
或者,调用可以为参数数组指定零个或多个参数,其中每个参数是一个可隐式转换的类型的表达式(第6.1节)到参数数组的元素类型。在这种情况下,调用创建参数数组类型的实例,其长度对应于参数的数量,使用给定的参数值初始化数组实例的元素,并使用新创建的数组实例作为实际参数。