简体   繁体   English

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

[英]C# Inconsistent results using params keyword

Given the following method: 给出以下方法:

static void ChangeArray(params string[] array) {

    for (int i = 0; i < array.Length; i++) 
        array[i] = array[i] + "s";
}

This works if I call it passing a array of strings: 如果我调用它传递一个字符串数组,这是有效的:

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

But will not work if I call it using string arguments: 但如果我使用字符串参数调用它将无法工作:

string Michael = "Michael";
string Jordan = "Jordan";
ChangeArray(Michael, Jordan); // This will NOT change the values of the variables

I understand that the compiler will wrap Michael and Jordan on an array, so shouldn't the results be the same on both cases? 我知道编译器会将Michael和Jordan包装在一个数组上,所以两种情况下结果不一样吗?

Your second example is essentially: 你的第二个例子基本上是:

string Michael = "Michael";
string Jordan = "Jordan";
{
    var tmp = new string[] {Michael, Jordan};
    ChangeArray(tmp);
}

so; 所以; actually, the values inside tmp were changed... but tmp was discarded afterwards, so you don't see anything. 实际上, tmp 的值已经改变了......但之后丢弃了tmp ,所以你什么都看不到。 params does not emulate ref - it won't do a position-wise update back into the original variables. params 并不模拟ref -它不会做的位置明智更新回原始变量。 Or in code, it is not the following: 或者在代码中,它不是以下内容:

string Michael = "Michael";
string Jordan = "Jordan";
{
    var tmp = new string[] {Michael, Jordan};
    ChangeArray(tmp);
    Michael = tmp[0];
    Jordan = tmp[1];
}

If you need it to behave like that, then code it like that - or use instead an overload that takes ref parameters. 如果你需要它那样做,然后像这些代码是-或改用一个重载需要ref的参数。

The reason is that string is an immutable type - you pass in string instances that get wrapped in an array. 原因是string是一个不可变类型 - 您传入包含在数组中的string实例。 The array now contains two new strings (with the same values that the original ones but different instances). 该数组现在包含两个新字符串(具有与原始字符串相同但不同实例的值)。 When you change the array, these copies are throw away and the array slot will hold a new string. 更改阵列时,这些副本将被丢弃,阵列插槽将保留一个新字符串。 When your function returns, the temporary array is thrown away. 当函数返回时,临时数组将被丢弃。 Thus your original input strings are never modified (they couldn't be anyway, since string is - again - immutable). 因此,您的原始输入字符串永远不会被修改(它们无论如何都不可能,因为string是 - 再次 - 不可变的)。

Edit I made an edit to this answer following Lee's argument in the comments (I'll leave the answer as is simply to keep the following discussion complete). 编辑我在评论中李的论点后对这个答案进行了编辑(我将保留答案,只是为了完成以下讨论)。 The immutable part is indeed irrelevant to the problem. 不可变部分确实与问题无关。 The main underlying issue is that changes are made to the temporary array that's thrown away. 主要的根本问题是对被丢弃的临时数组进行了更改。

This is weird (I didn't know this), but as specified . 这很奇怪(我不知道这个),但是如规定的那样

A parameter array permits arguments to be specified in one of two ways in a method invocation: 参数数组允许在方法调用中以两种方式之一指定参数:

The argument given for a parameter array can be a single expression of a type that is implicitly convertible (Section 6.1) to the parameter array type. 为参数数组提供的参数可以是可隐式转换(第6.1节)到参数数组类型的类型的单个表达式。 In this case, the parameter array acts precisely like a value parameter. 在这种情况下,参数数组的作用就像一个值参数。

Alternatively, the invocation can specify zero or more arguments for the parameter array, where each argument is an expression of a type that is implicitly convertible (Section 6.1) to the element type of the parameter array. 或者,调用可以为参数数组指定零个或多个参数,其中每个参数都是可隐式转换(第6.1节)到参数数组的元素类型的类型的表达式。 In this case, the invocation creates an instance of the parameter array type with a length corresponding to the number of arguments, initializes the elements of the array instance with the given argument values, and uses the newly created array instance as the actual argument. 在这种情况下,调用创建参数数组类型的实例,其长度对应于参数的数量,使用给定的参数值初始化数组实例的元素,并使用新创建的数组实例作为实际参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM