我有一个类,其中有3个字符串属性。我想将它们存储在列表中,以便当我更改列表中的字符串时,它们也会在类中更新。
如果我使用类对象,这将很容易实现,但是字符串似乎表现不同。它似乎为列表制作了对象的副本,而不是指向对象的指针。我应该如何在C#中做到这一点?如果这不可能,是否有更好的方法?
string
的问题在于它们是不可变的。换句话说,一旦创建了一个 string
,就不能再更改它。
因此,如果你想要“更改”一个 string
,你必须从 List
中删除原始字符串,并将结果存储回列表中。例如:
string a = "abcdefg";
List<String> list = new List<String>();
list.add(a);
a = a.Substring(0, 5);
string
a
所指向的内容从来没有发生过变化。它只是指向了一个新的 string
。字符串是不可变的。你可以改变一个引用来指向另一个字符串,但你不能修改一个字符串使其它引用的值也随之改变(除非使用不安全、完全危险的反射代码)。
你想要做的是通过使用可变的替代方案(如StringBuilder),或通过显式间接处理来处理这个问题。我将展示后者:
public class Props
{
private readonly string[] data = new string[2];
public string Foo {
get { return data[0]; }
}
public string Bar {
get { return data[1]; }
}
public IList<string> ModifyValueButNoInsertsList { get { return data;} }
}
在这种情况下,您应该考虑实际使用 string[]
而不是 IList
,因为它清晰地表明插入是被禁止的,只有对值进行修改。由于 string[]
实现了 IList<string>
,因此这不太可能成为问题。
C#中的字符串是不可变的,因此您无法更改C#中的字符串 - 您只能创建新字符串。
相反,您可以存储具有字符串成员的类。
class StringHolder {
public StringHolder(string s) { str = s;}
public string str;
}
...
List<StringHolder> l1 = new List<StringHolder>();
List<StringHolder> l2 = new List<StringHolder>();
List<StringHolder> l3 = new List<StringHolder>();
StringHolder h = new StringHolder("Test\n");
l1.add(h);
l2.add(h);
l3.add(h);
h.str = h.str.Replace("\n","");
现在所有的列表都引用同一个StringHolder,因此自然会看到相同的字符串。
另一种选择是将StringBuilder对象存储在列表中,而不是一个String。
class StringHolder
{
public string Value { get; set; }
}
不要只保留字符串,而是保留一个列表。这样,您就可以获取/设置Value
属性以更新字符串值。
由于字符串是不可变的,最简单的解决方法是存储一个只有一个元素的字符串数组的引用。然后,任何引用该数组的人都会注意到替换该元素。
你正在寻找一种可变字符串。有很多方法可以创建一个行为符合你要求的类。
最简单的方法是使用 StringBuilder 对象而不是字符串。你只需要小心不要创建新的 StringBuilder 对象,而是修改现有的对象。根据你的需求,这可能不是最佳选择。
另一种方法是创建自己的 String 包装类,可以自由地操纵它。缺点是你可能需要编写许多存根方法,这些方法调用内部字符串,具体取决于你想如何使用它。更容易的方法是公开一个读/写字符串属性。这样做的好处是可以定义你想要的行为,但在第一次编写时需要花费更长的时间。同样,你必须确保不创建包装类的新实例,而是仅修改类的内部字符串。
将您的字符串包装到自定义类中,这样可以让您在多个不同的位置之间共享它。您也可以选择存储字符数组。