繁体   English   中英

有没有办法检查两个具有相同值的字符串是否是 C# 中的同一个实例?

[英]Is there a way to check if two string with same value are the same instance in C#?

C#中的String是引用类型,但是它重写了==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 当您可能会使用许多可能具有相同值的字符串(基于读取控制台/文件输入、从数据库读取或以其他方式计算)时,显式实习对于减少内存很有用。

此外, string.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, d reference interned "cat"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM