简体   繁体   English

更改方法内的引用类型(字符串)

[英]Changing reference types(strings) inside methods

I am passing a string variable to a method. 我将字符串变量传递给方法。 I know strings are reference types but the value that I assign inside the method is lost. 我知道字符串是引用类型,但我在方法中分配的值丢失了。

public static void TestMethod(string myString)
{
    myString = "world";
}

static void Main(string[] args)
{
    string s = "hello";
    Console.WriteLine(s); // output is "hello"
    TestMethod(s);
    Console.WriteLine(s); // output is also "hello" not "world" !?
}

Anyway this does not happen with an array for example. 无论如何,例如,数组不会发生这种情况。 Can someone explain why might be the cause? 有人可以解释为什么可能是原因吗?

Because myString = "world" assigns a new string to the parameter, not updating the existing string. 因为myString = "world"会为参数指定一个新字符串,而不是更新现有字符串。 To update the original reference to the string you must pass the parameter with ref . 要更新对字符串的原始引用,必须使用ref传递参数。

public static void TestMethod(ref string myString)
{
    myString = "world";
}

static void Main(string[] args)
{
    string s = "hello";
    Console.WriteLine(s); // output is "hello"
    TestMethod(ref s);
    Console.WriteLine(s); // output is also "hello" not "world" !?
}

Yes, because without a ref (or out) you can't assign a new object to a parameter. 是的,因为没有ref(或out),您无法为参数分配新对象。 Since you didn't pass it in through a ref, the variable outside the method still references the original string which didn't change. 由于您没有通过ref传递它,因此方法外部的变量仍然引用未更改的原始字符串。 Consequently, strings are immutable, so you can't do anything to it without create a new string once it is instantiated. 因此,字符串是不可变的,因此在实例化后不创建新字符串就无法对其执行任何操作。

The array can be altered (or the contents of the array can be altered), because the references inside the array are not immutable (you can say reassign my_object 1 to equal "BLAH"). 可以更改数组(或者可以更改数组的内容),因为数组中的引用不是不可变的(可以说my_object 1重新分配为“BLAH”)。 You can replace a value in the array and have it accessible outside of the array, because the reference to the array outside of the method hasn't changed. 您可以替换数组中的值并使其可以在数组外部访问,因为对方法外部的数组的引用没有更改。

Link to String in MSDN (talks about immutability) 链接到MSDN中的字符串(谈论不变性)

For this to work you need to add the "ref" keyword to the parameter in the method signature. 为此,您需要将“ref”关键字添加到方法签名中的参数。

Though your string is passed by reference, when you pass it to your method you have 2 references to the same string - the one in the Main() and the one in TestMethod(). 虽然您的字符串是通过引用传递的,但是当您将它传递给您的方法时,您有2个对同一字符串的引用 - Main()中的一个和TestMethod()中的一个字符串。 When you assign a new value to the variable in the TestMethod() you are changing its reference, but not what Main()'s variable is referencing. 当您为TestMethod()中的变量分配新值时,您正在更改其引用,但不会更改Main()的变量引用的内容。

If you were able to just change the string from the TestMethod() instead of reassigning then you would see the effects in the Main(), but you can't with strings since they are immutable. 如果您只能从TestMethod()更改字符串而不是重新分配,那么您将在Main()中看到效果,但由于它们是不可变的,因此您不能使用字符串。

To play with this further you can try the following - change TestMethod() to receive a IList and add items to this list. 要进一步使用此功能,您可以尝试以下操作 - 更改TestMethod()以接收IList并将项添加到此列表中。 You can see these new items in the variable you passed in from Main(). 您可以在从Main()传入的变量中看到这些新项。 Now if you change TestMethod(IList listArg) to first reassign listArg to a new list (ie listArg = new List) and then add items, the list in Main() remains unchanged. 现在,如果您将TestMethod(IList listArg)更改为首先将listArg重新分配给新列表(即listArg = new List)然后添加项目,则Main()中的列表保持不变。 This is the same idea. 这是同样的想法。

Strings are immutable, which means that you can't change it's value, like you do with the items in an array. 字符串是不可变的,这意味着您无法更改它的值,就像您对数组中的项目所做的那样。 You can only replace a string object with a different string object. 您只能用不同的字符串对象替换字符串对象。

The same happens if you try to replace an array object. 如果您尝试替换数组对象,也会发生相同的情况。 This will put a new array in the parameter variable, but it will not change the variable that you used to call the method, and thus does not replace the array that you passed in: 这将在参数变量中放置一个新数组,但它不会更改用于调用方法的变量,因此不会替换传入的数组:

public static void TestMethod(string[] myArray) {
  myArray = new string[] { "world" };
}

Parameters are always passed by value unless you use the ref or out keywords. 除非使用refout关键字,否则始终按值传递参数。 For a reference type that means that you pass a copy of the reference. 对于引用类型,表示您传递引用的副本。

Using the ref keyword you pass the variable, so that you can change it in the method: 使用ref关键字传递变量,以便您可以在方法中更改它:

public static void TestMethod(ref string myString) {
  myString = "world";
}

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

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