因此,正如我们所知,对象(在当前示例中 - 字符串)相对于它们在堆中的引用进行比较。所以,如果:
string a = "something";
string b = "something";
bool isEqual = (a == b);
将 a 的值放入字符串池中,并在搜索完 b 的值后与 a 相同池,将为变量 b 分配相同的引用。好的,那很清楚。但是如果发生了什么:
string a = "somethingNew";
bool isEqual = (a == "somethingNew");
如何在内存中表示这样的比较文字(如果有的话)以及在这种情况下如何完成整个比较过程?
答案 0 :(得分:12)
对象可以相对于它们在堆中的引用进行比较。如果这是它们原生使用的方式,大多数对象都不会比较人类友好,因此像string
这样的事实上实现了相等运算符的重载更直观。 string
通过首先检查内存引用(首先调用==
)并且如果不是相同的引用来比较相等(通过相等object.ReferenceEquals(object, object)
运算符),然后回退到比较字符串中的字符,无论记忆位置如何。
字符串文字(例如"somethingNew"
)被编译为一个变量,在.NET调用实习内存池时引用该字符串值...这是一种具有相同值的所有字符串的含义(意思相同) case和characters)都作为指向实习池中单个引用的指针,而不是每个引用都有相同值的内存分配。这样可以节省内存,但需要在实习池中查找值。这是因为字符串是不可变的(只读),因此通过与+
或+=
运算符串联来更改字符串的值,否则实际上会创建一个全新的字符串。默认情况下,字符串变量不会被中断,除非它们是文字。
示例中字符串的比较将在初始字符串相等对象引用检查上成功,并返回true而不进行任何进一步的相等性分析。这将发生,因为您的变量是字符串文字,因此实习(具有相同的内存地址)。如果没有实习,那么无论内存位置如何,比较都会回到字符比较中。
您可以使用string.Intern(string)
答案 1 :(得分:5)
因此,正如我们所知,对象(在当前示例中 - 字符串)相对于它们在堆中的引用进行比较。
不正确的; ==
运算符可能会超载,<{1}}的确实重载。
但是如果发生了什么:
使用字符串比较;但是,即使它们不是:因为该数据来自文字(string
),因此“interning”会导致相同的字符串实例 - 所以即使它使用参考比较,它仍然可以工作。
答案 2 :(得分:1)
这仍然是完全相同的情况,您不必具有字符串文字的变量名称。请记住,字符串会覆盖operator ==(),因此您可以对字符串 content 进行比较,而不仅仅是普通对象比较。所以这也适用:
string tail = "New";
bool isEqual = (a == "something" + tail);
答案 3 :(得分:0)
'=='首先检查两个变量是否引用同一个对象。如果没有,则在内容本身进行实际值比较。
使用字符串常量作为:bool isEqual = (a == "somethingNew");
进行比较实际上会获得常量值,在所谓的池中搜索它,如果它有匹配,它会引用同一个对象吗?那么,它实际上将它分配为变量?对不起,这对我来说还有点不清楚。
最后一个(来自给定文章的一个例子):
string firstString = "deer";
string secondString = firstString;
string thirdString = "de" + 'e' + 'r';
cw(firstString == secondString); // True - same object
cw(firstString == thirdString); // True - equal objects
cw((object)firstString == (object)secondString); // True
cw((object)firstString == (object)thirdString); //False
在这种情况下,不应该在池中搜索thirdString的值,而整个变量是否要接收与firstString和secondString相同的对象的引用?