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

发布于 2024-11-27 15:36:24 字数 356 浏览 1 评论 0原文

我有以下代码

  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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

神魇的王 2024-12-04 15:36:24

字符串是不可变的,所以这是行不通的。当您尝试设置它时,您实际上将指针放到了旧字符串上,并在底层创建了一个新字符串。

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

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);
    }
}

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

请参阅 Jon Skeet 的回答,无疑对 C# 中的字符串有非常准确的解释,我什至不会打扰!

替代类名称:

  • PseudoMutableString
  • ICantBelieveItsNotMutable
  • HappyAndReferenceableString

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:

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);
    }
}

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 a SortOfMutableString.

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:

  • PseudoMutableString
  • ICantBelieveItsNotMutable
  • HappyAndReferenceableString
溺渁∝ 2024-12-04 15:36:24

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

相反,您可以创建一个具有可写 String 属性的可变 StringHolder 类。

You're changing the s reference to refer to a different String 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 writable String property.

哑剧 2024-12-04 15:36:24

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

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

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

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

所以特别是,列表对变量s一无所知 - 它知道传递给Add >;该值恰好是调用 Adds 的值,仅此而已。

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

No, it shouldn't equal world. The value of the variable s is a reference. When you call l.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:

  • A variable (which has a name and a value)
  • A reference (a value which allows you to navigate to an object, or null)
  • An object

So in particular, the list doesn't know anything about the variable s - it knows about the value which was passed into Add; that value happened to be the value of s at the time Add was called, that's all.

You may find these articles helpful:

雨落星ぅ辰 2024-12-04 15:36:24

不,涉及两个不同的参考。一个名为 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<StringWrapper>();
 l.Add(s);
 s.TheString = "World";

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

No, there are two different references involved. One called s and one that's at List[0]. When you say l.Add(s) you are setting the list reference to the same address as s, but then when you assign s to "world", then s will point to the new string, leaving List[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 and List[0] both refer to that object, and then that object's reference to a string can change and both will see it.

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

Then you can do:

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

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].

↘紸啶 2024-12-04 15:36:24

变量是一个对象引用,而不是对象本身。 s = "world" 表示“使 s 引用字符串 "World") - 它不会以任何方式影响字符串 s 之前引用的“hello” 此外,C# 中的字符串始终是不可变的,但是您可以创建第一个列表元素(当前引用 ”)。 hello") 引用不同的字符串:l[0] =“世界”

A variable is an object reference, not an object itself. s = "world" says "make s refer to the string "World") - it does not in any way affect the string "hello" that s 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".

柠北森屋 2024-12-04 15:36:24

这里的其他两个答案很好地说明了为什么您尝试的方法不起作用,但您正在寻找实现所需效果的解决方案。将字符串(属性)包装在对象内部。然后您可以更改该字符串,它将反映在集合中。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文