如何获取可变字符串列表?

我有以下代码

List l = new List(); String s = "hello"; l.Add(s); s = "world"; 

当我设置一些断点并完成程序时,在执行最后一行之后,列表中的值仍然是hello而不是world

它不应该等于world吗? 字符串不是一个对象,我不只是将一个指针插入列表中吗? 稍后如果我将字符串更改为指向不同的值(“world”),为什么我的列表仍然引用旧值?

我怎样才能达到理想的效果? 非常感谢!

字符串是不可变的,因此不起作用。 当您尝试设置它时,实际上是将指针放到旧字符串上并在引擎盖下创建一个新字符串。

要获得所需的效果,请创建一个包装字符串的类:

 public class SortOfMutableString { public string Value {get;set;} public SortOfMutableString(string s) { Value = s; } public static implicit operator string(SortOfMutableString s) { return s.Value; } public static implicit operator SortOfMutableString(string s) { return new SortOfMutableString(s); } } 

并在列表中使用它。 然后引用将指向类,但您可以在其中包含字符串值。 为了使它更好,请覆盖与字符串之间的implicit强制转换,这样您甚至不需要看到您正在与SortOfMutableString

请参阅Jon Skeet的回答毫无疑问是对C#中字符串的非常准确的解释,我甚至都不打扰!

替代类名:

  • PseudoMutableString
  • ICantBelieveItsNotMutable
  • HappyAndReferenceableString

您正在更改s引用以引用其他String实例。
字符串是不可改变的; 无法更改添加到列表中的现有实例。

相反,您可以使用可写的String属性创建可变StringHolder类。

不,它不应该等于world 。 变量s的值是参考。 当您调用l.Add(s) ,该引用l.Add(s) 传递给列表。 所以列表现在包含对字符串“hello”的引用。

您现在将s的值更改为对字符串“world”的引用。 这根本不会改变列表。

区分三个非常不同的概念很重要:

  • 变量(具有名称和值)
  • 引用(允许您导航到对象的值,或null
  • 一个东西

所以特别是,列表对变量 s一无所知 – 它知道传递给Add ; 那个值碰巧是在调用Add时的s值,就是这一切。

您可能会发现这些文章很有用:

  • 值和引用
  • 参数传递C#

不,涉及两个不同的参考。 一个叫做s ,一个叫做List[0] 。 当您说l.Add(s)您将列表引用设置为与s相同的地址时,但是当您将s指定给“world”时,则s将指向新字符串,而List[0]指向旧字符串。

如果你真的想要做你喜欢的事情,你需要将字符串包装在另一个包含字符串的对象中,这样sList[0]都引用该对象,然后该对象引用一个字符串可以改变,两者都会看到它。

  public class StringWrapper { public string TheString { get; set; } } 

然后你可以这样做:

  var s = new StringWrapper { TheString = "Hello" }; var l = new List(); l.Add(s); s.TheString = "World"; 

而现在l[0].TheString也将成为世界。 这是有效的,因为在这种情况下我们不会更改List [0]或s中的引用,而是它们由s和List [0]引用的对象的内容。

变量是对象引用 ,而不是对象本身。 s = "world"表示“make s引用字符串"World" ) – 它不会以任何方式影响s先前引用的字符串"hello" 。此外,C#中的字符串总是不可变的。但是,你可以,使第一个列表元素(当前引用"hello" )引用不同的字符串: l[0] = "world"

这里的另外两个答案很好地说明了你为什么尝试没有“工作,但你正在寻找一个解决方案,以达到你想要的效果。 将字符串(属性)包装在对象内部。 然后你可以改变那个字符串,它将反映在集合中。