我对字符串有一个疑问。 我们怎样才能获得字符串的记忆?
是String是引用类型还是值类型?
1)如果是参考类型,则执行以下代码
List<String> strLst = new List<string>() { "abc","def","12"};
strLst.ForEach(delegate(string s)
{
if (s == "12")
{
s = "wser";
// I doubted whether = operator is overloaded in string class
//StringBuilder sb = new StringBuilder(s);
//s = sb.Append("eiru").ToString();
s = String.Concat(s, "sdf");
}
});
看到字符串的值没有改变。我的问题是为什么字符串值没有改变? 如果是引用类型,则应更改字符串值。
class emp
{
public string id;
}
List<emp> e = new List<emp>() { new emp() { id = "sdf" }, new emp() { id = "1" }, new emp() { id = "2" } };
e.ForEach(delegate(emp em)
{
if (em.id == "1")
em.id = "fghe";
});
此值已更改,因为emp
是引用类型
2)如果string
是值类型
public sealed class String : IComparable, ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>
那么为什么他们提到那个字符串是一个类?
答案 0 :(得分:2)
这是因为这部分:
s = "wser";
这完全等同于:
s = new String ("wser");
当你写这个时,实例化一个新对象,它的引用存储在s中。因此,先前的引用在函数范围内完全丢失,并且在范围之外没有发现任何变化。
因此,要注意在另一个范围中更改的引用类型的更改,您无法创建新实例并将其分配给变量名称,您必须修改原始引用本身(这不是可能是Java中的字符串对象 - 字符串是不可变的。)
答案 1 :(得分:2)
System.String
类型确实是一种引用类型,虽然相当奇怪。从开发人员的角度来看,它是不可改变的,而CLR对它的看法就像一个值类型,所以你做同样的事情也不会有太大的错误。
Jon Skeet's article,也很好地解释了这种好奇心:
请注意许多类型(例如字符串) 以某种方式出现为价值类型, 但事实上是参考类型。这些 被称为不可变类型。这个 表示一旦实例出现 构建,它不能改变。这个 允许引用类型执行 类似于某种方式的值类型 - 特别是,如果你持有对不可变对象的引用,那么 回来时会觉得舒服 从方法或传递到另一个方法 方法,安全知识它 不会在你背后改变。 这就是为什么,例如, string.Replace不会改变 字符串被调用,但返回一个 带有新字符串数据的新实例 in - 如果原始字符串是 改变了,任何其他变量持有 对字符串的引用会看到 改变,这很少是什么 期望的。
答案 2 :(得分:1)
如果将对象的引用存储在变量中然后更改引用,则对象不会更改,只会更改变量。你正在改变em的属性,从而影响变量em的对象引用。如果您改为em = something
,它的行为将类似于String示例,并且不会影响任何内容。
答案 3 :(得分:0)
String类型是引用类型,但它是不可变的。这意味着您无法更改字符串的内容。
它实际上表现得像一个值类型,但只传递引用,而不是整个字符串对象。
答案 4 :(得分:0)
从MSDN在线页面 - string
字符串是不可变的 - 字符串对象的内容无法更改。虽然string是引用类型,但是定义了相等运算符(==和!=)来比较字符串对象的值,而不是引用。
答案 5 :(得分:0)
String是引用类型。
列表中的字符串在您的示例中没有更改的原因是该方法无法访问列表中的项目,它只获取引用的副本。参数s
只是方法中的局部变量,因此为其指定新值不会影响列表的内容。