可能的意外参考比较按预期工作

jtr*_*hde 6 c# asp.net .net-4.5

我有类似以下代码:

this.Session[key] = "foo";

if ((this.Session[key] ?? string.Empty) == "foo")
{
    //do stuff
}
Run Code Online (Sandbox Code Playgroud)

当然,这会产生"可能的非预期参考比较按预期工作"的情况.这里有很好的解决方案,我已经知道修复是在string看到代码后立即将会话变量转换为a .

但是,代码已有多年历史,并且自最初编写以来从未更改过.直到本周在我们的测试环境中,if语句被评估为true并执行了该//do stuff部分.这个错误的代码仍然在我们的生产环境中按预期工作.

怎么会这样?这些编写的代码没有理由按照预期工作; 然而它确实如此,并且仍然在生产中.什么会改变,使这个代码不应该工作,但做了,突然停止工作(或者更确切地说,表现得像它应该有的)?

Jak*_*rtz 4

字符串文字“foo”被interned。这意味着每次使用它时,都会引用同一个对象。

公共语言运行时通过维护一个称为实习池的表来保存字符串存储,该表包含对程序中以编程方式声明或创建的每个唯一文字字符串的单个引用。因此,具有特定值的文字字符串实例在系统中仅存在一次。

例如,如果将相同的文字字符串分配给多个变量,运行时将从内部池中检索对文字字符串的相同引用并将其分配给每个变量。

这就是为什么这object.ReferenceEquals("foo", "foo")是真的。

如果对动态创建的字符串执行相同的操作,它将不会被保留并且引用将不相等

object str = new StringBuilder().Append("f").Append("oo").ToString(); // str = "foo"
object.ReferenceEquals(str, "foo");                                   // false
Run Code Online (Sandbox Code Playgroud)

根据实现的不同,字符串驻留的工作方式可能有所不同,这就是为什么在通过引用比较字符串时,您可以在不同的环境中获得不同的行为。