如何获取可变字符串列表?
我有以下代码
List<String> l = new List<String>();
String s = "hello";
l.Add(s);
s = "world";
当我设置一些断点并执行程序时,执行最后一行后,列表中的值仍然是 hello
而不是 world
。
它不应该等于 world
吗?字符串不是一个对象吗?我不只是在列表中插入一个指针吗?稍后,如果我更改字符串以指向不同的值(“world”),为什么我的列表仍然引用旧值?
怎样才能达到我想要的效果呢? 多谢!
I have the following piece of code
List<String> l = new List<String>();
String s = "hello";
l.Add(s);
s = "world";
When I set up some breakpoints and go through the program, after executing the last line, the value in the list is still hello
instead of world
.
Shouldn't it equal world
? Isn't a string an object, and am I not just inserting a pointer into the list? Later on if I change the string to point to a different value ("world"), why is my list still referencing the old value?
How can I get my desired effect ?
Thanks a lot!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
字符串是不可变的,所以这是行不通的。当您尝试设置它时,您实际上将指针放到了旧字符串上,并在底层创建了一个新字符串。
要获得所需的效果,请创建一个包装字符串的类:
并在列表中使用它。然后引用将指向该类,但您可以在其中包含字符串值。为了使其更好,请覆盖字符串之间的
隐式
转换,这样您甚至不需要看到您正在与SortOfMutableString
交谈。请参阅 Jon Skeet 的回答,无疑对 C# 中的字符串有非常准确的解释,我什至不会打扰!
替代类名称:
Strings are immutable so that won't work. When you attempt to set into it, you actually drop the pointer to the old string and create a new one under the hood.
To get the desired effect, create a class that wraps a string:
And use this in your list. Then references will point to the class, but you can contain the string value inside. To make it even better, override
implicit
casting to and from string so you don't even need to see that you are talking to aSortOfMutableString
.Refer to Jon Skeet's answer for undoubtedly a very accurate explanation about string's in C#, I'm not even going to bother!
Alternative class names:
您正在更改
s
引用以引用不同的String
实例。字符串是不可变的;无法更改您添加到列表中的现有实例。
相反,您可以创建一个具有可写
String
属性的可变StringHolder
类。You're changing the
s
reference to refer to a differentString
instance.Strings are immutable; it is impossible to change the existing instance that you added to the list.
Instead, you can create a mutable
StringHolder
class with a writableString
property.不,它不应该等于
world
。变量s
的值是一个引用。当您调用l.Add(s)
时,该引用将按值传递到列表。所以列表现在包含对字符串“hello”的引用。现在,您将
s
的值更改为对字符串“world”的引用。这根本不会改变列表。区分三个截然不同的概念非常重要:
null
)所以特别是,列表对变量
s
一无所知 - 它知道传递给Add
的值 >;该值恰好是调用Add
时s
的值,仅此而已。您可能会发现这些文章很有帮助:
No, it shouldn't equal
world
. The value of the variables
is a reference. When you calll.Add(s)
, that reference is passed by value to the list. So the list now contains a reference to the string "hello".You now change the value of
s
to a reference to the string "world". That doesn't change the list at all.It's important to distinguish between three very different concepts:
null
)So in particular, the list doesn't know anything about the variable
s
- it knows about the value which was passed intoAdd
; that value happened to be the value ofs
at the timeAdd
was called, that's all.You may find these articles helpful:
不,涉及两个不同的参考。一个名为
s
,另一个位于List[0]
。当您说l.Add(s)
时,您将列表引用设置为与s
相同的地址,但是当您将s
分配给“world”,那么s
将指向新字符串,而List[0]
则指向旧字符串。如果您确实想做类似您所要求的事情,则需要将字符串包装在另一个包含字符串的对象中,以便
s
和List[0]
两者都引用该对象,然后该对象对字符串的引用可以更改,并且两者都会看到它。然后你可以这样做:
现在
l[0].TheString
也将成为世界。这是可行的,因为在这种情况下,我们不会更改 List[0] 或 s 中的引用,而是更改 s 和 List[0] 引用的对象的内容。No, there are two different references involved. One called
s
and one that's atList[0]
. When you sayl.Add(s)
you are setting the list reference to the same address ass
, but then when you assigns
to "world", thens
will point to the new string, leavingList[0]
pointing to the old string.If you really want to do something like what you are asking, you'd need to wrap the string in another object that contains a string, so that
s
andList[0]
both refer to that object, and then that object's reference to a string can change and both will see it.Then you can do:
And now
l[0].TheString
will be world too. This works because in this case we are not changing the reference in List[0] or s, but they contents of the object referred to by s and List[0].变量是一个对象引用,而不是对象本身。
s = "world"
表示“使s
引用字符串"World"
) - 它不会以任何方式影响字符串
此外,C# 中的字符串始终是不可变的,但是您可以创建第一个列表元素(当前引用s
之前引用的“hello””)。 hello"
) 引用不同的字符串:l[0] =“世界”
。A variable is an object reference, not an object itself.
s = "world"
says "makes
refer to the string"World"
) - it does not in any way affect the string"hello"
thats
was previously referring to. Furthermore, strings in C# are always immutable. You can, however, make the first list element (which currently refers to"hello"
) refer to a different string:l[0] = "world"
.这里的其他两个答案很好地说明了为什么您尝试的方法不起作用,但您正在寻找实现所需效果的解决方案。将字符串(属性)包装在对象内部。然后您可以更改该字符串,它将反映在集合中。
The other two answers here did a great job of saying why what you tried didnt' work, but you were looking for a solution for your desired effect. Wrap a string (property) inside of an object. Then you can change that string and it will be reflected in the collection.