提问人:Ryan Liu 提问时间:12/23/2022 最后编辑:M. JustinRyan Liu 更新时间:11/7/2023 访问量:405
有没有办法检查两个具有相同值的字符串是否是 C# 中的同一实例?
Is there a way to check if two string with same value are the same instance in C#?
问:
C# 中的字符串是一种引用类型,但它已被重写,并比较字符串的值。有没有办法检查两个字符串是否确实是同一个实例并指向同一个内存?==
Equals()
甚至将返回 true,因为它只是调用 .Object.ReferenceEquals("A", "A")
==
此测试将通过。所以还在等待检查是否相同的实例。
[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);
}
}
答:
9赞
Kit
12/23/2022
#1
您的测试通过,因为字符串文字会自动嵌入,这意味着它们共享相同的内存。因为它们共享相同的内存,所以每种形式的相等都将返回:、、、通过指针进行固定和比较,以及 。true
ReferenceEquals
Equals
==
现在,非文字不会被隔离,这将使你的测试失败。例如,对于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"
评论
Object.ReferenceEquals("A", "AB".Substring(1))