当前位置: 首页 > 编程语言 > C#

引用值类型共享的相等性

时间:2023-04-10 19:25:35 C#

引用值类型的相等性我做了一些ref关键字测试,有一个我看不懂:staticvoidTest(refinta,refintb){Console.WriteLine(Int32.ReferenceEquals(a,b));}staticvoidMain(string[]args){inta=4;测试(参考一,参考一);控制台.ReadLine();}为什么这段代码显示为False?我知道int是一个值类型,但这里它应该传递对同一个对象的引用。为什么此代码显示False?因为inta和intb在调用object.ReferenceEquals时被装箱。每个整数都被打包到一个对象实例中。因此,您实际上是在比较两个明显不相等的盒装值之间的引用。如果查看该方法生成的CIL,您可以很容易地看到:Test:IL_0000:nopIL_0001:ldarg.0LoadargumentaIL_0002:ldind.i4IL_0003:boxSystem.Int32IL_0008:ldarg.1LoadargumentbIL_0009:ldind.i4IL_000A:boxSystem.Int32IL_000F:callSystem.Object.ReferenceEqualsIL_0014:callSystem.Console.WriteLineIL_0019:nopIL_001A:ret通过使用可验证的CIL(比如@leppie的回答)或者不安全的代码,你可以检查对于内存位置的相等性:unsafestaticvoidMain(string[]args){inta=4;整数b=5;Console.WriteLine(测试(refa,refa));//TrueConsole.WriteLine(Test(refa,refb));//错误的;}unsafestaticboolTest(refinta,refintb){fixed(int*refA=&a)fixed(int*refB=&b){returnrefA==refB;这不能直接在C#中完成。但是,您可以在可验证的CIL中实现它:.methodpublichidebysigstaticboolTest(!!T&a,!!T&b)cilmanaged{.maxstack8ldarg.0ldarg.1ceqret}testinta=4,b=4,c=5;int*aa=&a;//这个对象需要不安全的o=a,p=o;Console.WriteLine(测试(refa,refa));//真正的控制台。WriteLine(测试(refo,refo));//TrueConsole.WriteLine(Test(refo,refp));//错误Console.WriteLine(Test(refa,refb));//错误控制台.WriteLine(Test(refa,refc));//错误Console.WriteLine(Test(refa,ref*aa));//True//以上所有内容都适用于字段、参数和局部变量请注意,这实际上上面没有检查相同的引用,但更细化,因为它确保两者来自相同的“位置”(或者是从同一个变量引用)。这是第3行,它返回false,即使o==p返回true。然而,这种“位置”测试的用处非常有限。我知道,int是一个值类型,但这里它应该传递对同一个对象的引用。是的,传递给方法的引用是相同的,但它们在ReferenceEquals方法中被装箱(转换为对象/引用类型)。这就是测试返回false的原因,因为由于装箱,您正在比较对两个不同对象的引用。请参阅:比较值类型时的Object.ReferenceEquals方法。如果objA和objB是值类型,则在将它们传递给ReferenceEquals方法之前将它们装箱。这意味着如果objA和objB表示值类型的相同实例,ReferenceEquals方法仍然返回false这里的混淆是因为与指针(如*)不同,C#中的“ref”不是类型的一部分,而是方法的一部分签名部分。它适用于参数,意思是“不得复制”。这并不意味着“此参数具有引用类型”。ref传递的参数并不代表一个新的存储位置,而是一个已有位置的别名。如何创建别名在技术上是一个实现细节。大多数时候,别名是作为托管引用实现的,但并非总是如此。例如,在一些与异步相关的情况下,对数组元素的引用可以在内部表示为数组和索引的组合。基本上出于所有目的,您的a和b仍然被C#理解为int类型的变量。在像a+b或SomeMethod(a,b)这样的任何带有int值的表达式中使用它们是合法且完全正常的,在这些情况下,使用存储在a和b中的实际int值。实际上,没有将“引用”作为可以在C#中直接使用的实体的概念。与指针不同,必须假定托管引用的实际值可以随时被GC更改,甚至可以异步更改,因此托管引用的有意义场景集将非常有限。以上就是C#学习教程:引用值类型相等的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权请点击右侧联系管理员删除。如需转载请注明出处: