是否有一种方法来检查如果两个字符串具有相同的值是在c#相同的实例?



String在c#中是一个引用类型,但是它已经覆盖了==Equals()来比较字符串的值。是否有一种方法来检查两个字符串是否确实是相同的实例,并指向相同的内存?

即使Object.ReferenceEquals("A", "A")也会返回true,因为它只调用==

此测试将通过。所以仍然在等待检查是否相同的实例。

[Test]
public void TestString()
{
var a = "A";
var b = "A";
var c = a;
Assert.IsTrue((object)a == (object)b);
Assert.IsTrue(ReferenceEquals(a,b));  //It is same as objA == objB
Assert.IsTrue(Object.ReferenceEquals(a,b));
Assert.AreEqual(a,b);
Assert.AreSame(a, b);
unsafe
{
TypedReference tra = __makeref(a);
IntPtr ptra = (IntPtr)(&tra);

TypedReference trb = __makeref(b);
IntPtr ptrb = (IntPtr)(&trb);
Assert.AreNotEqual(ptra, ptrb);
Assert.AreNotSame(ptra, ptrb);

TypedReference trc = __makeref(c);
IntPtr ptrc = (IntPtr)(&trc);
Assert.AreNotEqual(ptra, ptrc); 
Assert.AreNotSame(ptra, ptrc);
Assert.IsFalse(ptra == ptrc);
}

}

您的测试通过了,因为字符串字面值被自动存储,这意味着它们共享相同的内存。因为它们共享相同的内存,所以每一种形式的相等都将返回trueReferenceEqualsEquals,通过指针进行固定和比较,以及==

现在,非字面量没有被拘禁,这将使您的ReferenceEquals测试失败。例如,对于

var a = Console.ReadLine(); // assume user enters cat
var b = Console.ReadLine(); // assume user enters cat

ReferenceEquals将返回false。但是如果你把代码改成

var a = string.Intern(Console.ReadLine()); // assume user enters cat
var b = string.Intern(Console.ReadLine()); // assume user enters cat

你又回到了ReferenceEquals返回true的状态。

简而言之,肯定有一种方法可以使用ReferenceEquals或通过指针来检查两个字符串是否为相同的引用。

顺便说一下,如果您截取了其中一个输入,这并不意味着另一个输入也被截取了,除非您对两个输入都调用了Intern。当您可能要处理许多字符串时,显式实习对于减少内存非常有用,这些字符串可能基于读取控制台/文件输入、从数据库读取或以其他方式计算而具有相同的值。

同时,字符串。IsInterned在一些有限的情况下是有用的,例如,可能用于检测字符串是否因为某些原因没有被拘禁,而你期望它被拘禁。

最后,这里有几个有趣的插图。考虑

var c = "cat";
var d = new string("cat");
var e = c;

然后这些断言,

Assert.IsTrue(ReferenceEquals(c,d)); // fails, c is interned, d is not
Assert.IsTrue(ReferenceEquals(c,e)); // succeeds, both c and e reference interned "cat"

最新更新