<object> 如果方法都是引用类型,为什么将字符串传递给方法的行为与 List 不同?



我正在阅读一个代码,让我停在某行:

List<object> props = new List<object>();
DoWork(param1, param2, props);
//props.Count grew up

我在想更改其范围之外的变量需要将其作为outref传递,但后来我意识到,除非DoWork方法更改props引用,例如:

props = new List<object>();

引用将指向同一位置。所以这里没有必要使用ref

然后我为string类型创建了一个方法:

static void ChangeMe(string str)
{
str = "W77";
}
public static void Main(string[] args)
{
string str = "p1";
ChangeMe(str);
//str is still "p1"
}

如果促使 List 在其范围之外更改的行为是它是引用类型,那么如果它没有在被调用方方法中重新分配并且它是像List<object>这样的引用类型,为什么string不更改?

原因是因为string是C#中的不可变类型,因此每当您"更改"它时,实际上您正在做的是使用新值创建一个新string并引用它。

调用ChangeMe时,将创建对同一字符串的新引用。然后在该方法中,您将新引用引用到一个全新的字符串,这不会影响Main中定义的先前字符串。

  • 对于为什么字符串不可变,请阅读: 为什么 .NET 字符串是不可变的?
  • 另外:C# 中的可变字符串和不可变字符串有什么区别?

在函数ChangeMe中,您有一个对传入对象的引用的本地副本。当你在str中存储一些东西时,你基本上用一个新的引用替换了该引用。不可变性在这里不起作用,因为您实际上并没有尝试修改str引用的对象。因此,您现在在str中存储了一个新引用,该引用指向使用字符串文字"W77"时由字符串构造函数创建的新对象。正如您所指出的,您可以通过refout将其置于功能范围之外

最新更新