【问题标题】:Why does object comparison in C# work strange?为什么 C# 中的对象比较工作起来很奇怪?
【发布时间】:2012-07-02 20:50:42
【问题描述】:

当我比较两个类型为 object 且都包含相同值的变量时, 使用== 运算符的比较结果产生false

object Var1 = "X";
object Var2 = "X";

// This produces false result
bool Match = Var1 == Var2;

为什么会这样?

编辑:以上是实际工作的代码!

我基于我的真实代码 像这样并且不起作用:

ChoiceValue = Choice.GetValue(FieldTemplate.ValueDataType);
if (ChoiceValue == Field.Value) RadioButton.IsChecked = true;

ChoiceValueobject 并且 Field.Value 是类型为 object 的属性。

显然在不同情况下的工作方式不同。

【问题讨论】:

标签: c# comparison string-comparison


【解决方案1】:

这种特定情况返回 false 的原因是您的字符串没有被保留。 (String interning)

当我测试它时,我得到了正确的结果,因为我的字符串被保留了。

在您的情况下,这会导致 object == 运算符返回 false,因为 它通过引用进行比较

您的字符串没有被保留的原因是因为您正在比较动态构建的字符串(这意味着它们在编译时是未知的,但在运行时是已知的)。

如果你绝对必须使用对象变量,你可以使用Equals而不是==,或者你可以手动使用String.Intern实习字符串

这种情况是引用类型字符串试图表现得像值类型的异常。这意味着它们在使用字符串 == 运算符时按值进行比较。但是,当您有对象时,它使用 object == 运算符,按引用进行比较。

string 的文档中对此进行了解释。

【讨论】:

    【解决方案2】:

    在您编辑的问题中,您会遇到这种行为,因为 == 比较的是参考而不是它们的值。

    在字符串值的情况下,由于字符串暂留,它似乎按预期工作。这里您的Var1Var2 指向字符串“X”的单个副本,并且由于== 比较引用它给出了真实的结果。

    字符串实习。这是一种存储任何字符串的副本的方法。

    你可能会看到:Understanding string interning

    【讨论】:

    • 进一步说明:((string)Var1) == ((string)Var2) 将是true,不是吗?
    【解决方案3】:

    运算符 == 比较参考和它们的值。

    (参考比较)

    表示var1指向内存中的位置xxxx,var2指向内存中的yyyy。所以它们是不同的对象。

    如果您的代码是:

    object Var1 = "X";
    object Var2 = Var1;
    
    bool Match = Var1 == Var2;
    

    匹配为真,因为 Var1Var2 都将指向内存中的 xxxx,因此是同一个对象。

    (深度对象比较)

    您可以使用 Equals 比较对象内部的值。因此,当您比较 Var1(在 xxxx 位置)和 Var2(yyyy 位置)时,如果碰巧两者都包含相同的值(在本例中为字母 X),那么它将返回 true,否则返回 false。 这样做的代码是:

    object Var1 = "X";
    object Var2 = "X";
    
    // This produces false result
    bool Match = Var1.Equals(Var2);
    

    注意:此答案仅适用于未插入字符串的情况。如果它们被实习,两个对象将指向内存中的相同位置

    【讨论】:

    • Var1 和 Var2 将(在正常情况下)是同一个对象,因为字符串是 intern
    【解决方案4】:

    【讨论】:

    • 我没有投反对票。我想无论是谁做的,都是因为你发布了一个关于字符串比较而不是对象比较的链接?无论如何..我会补偿它:)
    • 我投了反对票,因为您提供的链接都不是 OP 回答错误的原因。肯德尔弗雷是对的。 (还有DVd,因为你不回答问题,你只是列出来源)
    • 但是来源不是用满了吗?您不应该知道原因吗,我提供的资料中对此进行了详细说明?我还提供了 stachoverflow 中已经提出的相关/类似问题的链接,这不是很好吗?无论如何感谢您的回复。
    【解决方案5】:

    因为它比较对象的引用。最好的方法是 override Equals 或重载 == 运算符。

    【讨论】:

    • 它们都已经为字符串重载,因此调用可以解决问题,但是使用的 == 版本基于参数的编译时类型而不是运行时类型,因此在这种特殊情况下它不会影响结果
    【解决方案6】:
    Why is this happening?
    

    因为它匹配引用而不是它的值为 false。

    在字符串== 中比较它们的值。

    试试Var1.Equals(Var2);

    【讨论】:

    • 我将 OP 代码复制到 LINQPad 中,并将最后一行替换为 (Var1 == Var2).Dump();
    • ...aaand 你得到了转储结果这就是为什么:)
    • @KendallFrey:不要转储,然后看看会发生什么。
    • @Nikhal:那我不会得到任何输出。
    • 结果应该为真,因为 "X" 是 inned 并且 var1 和 var2 指向同一个对象。如果字符串是动态构建的并且两者都具有“X”的值,那么结果应该是错误的,因为它(通常)将是两个不同的对象。在 OP 的情况下,它们应该是同一个对象,这就是 @kendallfrey 得到该结果的原因
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-08
    • 2011-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多