关于ReferenceEquals(object a, object b)的问题
昨天跟几个同事一起讨论了下object.ReferenceEquals(object a, object b)方法, 其中有这样一个问题:
object c = "foo";
string d = "foo";
bool i = ReferenceEquals(c, d); //return true
string d = "foo";
bool i = ReferenceEquals(c, d); //return true
为什么返回的是true?
c和d都是调用了string的赋值构造函数,string的赋值构造函数是不会在堆上申请空间的。那么如果string赋值构造函数不会在堆上申请空间,又不是指针,何来引用,看了下这段代码的IL,
IL_0000: nop
IL_0001: ldstr "foo"
IL_0006: stloc.0
IL_0007: ldstr "foo"
IL_000c: stloc.1
IL_0013: ldloc.1
IL_0014: ldloc.0
IL_0015: call bool [mscorlib]System.Object::ReferenceEquals(object,
object)
IL_0001: ldstr "foo"
IL_0006: stloc.0
IL_0007: ldstr "foo"
IL_000c: stloc.1
IL_0013: ldloc.1
IL_0014: ldloc.0
IL_0015: call bool [mscorlib]System.Object::ReferenceEquals(object,
object)
的确都是在栈上分配的, 并且第一个"foo"和第二个"foo"进栈的顺序是不一样的,引用怎么可能一样?
另外, object类的ReferenceEquals(object a, object b)的实现是这样的:
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static bool ReferenceEquals(object objA, object objB)
{
return (objA == objB);
}
public static bool ReferenceEquals(object objA, object objB)
{
return (objA == objB);
}
只做简单的"=="比较. 百思不得其解.. 最后一个同事在网上找到这样一句话:
.NET 运行时在应用程序域中保留了一个字符串常值池, 当它将一个程序集加载到应用程序域中时,将该程序集的字符串常值与应用程序域的字符串常值池合并,从而避免了字符串常值的重复。(这样所有字符串常值只有一个副本,就可以对字符串常值进行引用比较,而且因为引用只需比较地址即可,所以比值比较快得多。)
posted on 2008-05-23 12:54 Daniel Luo 阅读(437) 评论(0) 编辑 收藏 举报