C#使用params关键字的结果不一致

Bru*_*tos 16 c# pass-by-reference pass-by-value params

给出以下方法:

static void ChangeArray(params string[] array) {

    for (int i = 0; i < array.Length; i++) 
        array[i] = array[i] + "s";
}
Run Code Online (Sandbox Code Playgroud)

如果我调用它传递一个字符串数组,这是有效的:

string[] array = {"Michael", "Jordan"} // will become {"Michaels", "Jordans"}
ChangeArray(array);
Run Code Online (Sandbox Code Playgroud)

但如果我使用字符串参数调用它将无法工作:

string Michael = "Michael";
string Jordan = "Jordan";
ChangeArray(Michael, Jordan); // This will NOT change the values of the variables
Run Code Online (Sandbox Code Playgroud)

我知道编译器会将Michael和Jordan包装在一个数组上,所以两种情况下结果不一样吗?

Mar*_*ell 23

你的第二个例子基本上是:

string Michael = "Michael";
string Jordan = "Jordan";
{
    var tmp = new string[] {Michael, Jordan};
    ChangeArray(tmp);
}
Run Code Online (Sandbox Code Playgroud)

所以; 实际上,里面的值tmp 改变了......但tmp之后被丢弃了,所以你什么也看不见.params没有效仿ref-它不会做的位置明智更新回原始变量.或者在代码中,它不是以下内容:

string Michael = "Michael";
string Jordan = "Jordan";
{
    var tmp = new string[] {Michael, Jordan};
    ChangeArray(tmp);
    Michael = tmp[0];
    Jordan = tmp[1];
}
Run Code Online (Sandbox Code Playgroud)

如果你需要它的行为,那么就像那样编码 - 或者使用带ref参数的重载.


xxb*_*bcc 5

原因是它string是一个不可变类型 - 你传入string包含在数组中的实例.该数组现在包含两个新字符串(具有与原始字符串相同但不同实例的值).更改阵列时,这些副本将被丢弃,阵列插槽将保留一个新字符串.当函数返回时,临时数组将被丢弃.因此,您的原始输入字符串永远不会被修改(它们无论如何都不可能,因为string- 再次 - 不可变).

编辑我在评论中李的论点后对这个答案进行了编辑(我将保留答案,只是为了完成以下讨论).不可变部分确实与问题无关.主要的根本问题是对被丢弃的临时数组进行了更改.

  • 这与字符串不可变无关. (2认同)