当前位置: 首页 > 知识库问答 >
问题:

为什么比较两个字符串作为对象会导致意外的结果

叶允晨
2023-03-14

考虑下面的代码。

object str = new string(new char[] { 't', 'e', 's', 't' });
object str1 = new string(new char[] { 't', 'e', 's', 't' });
Console.WriteLine(str==str1); // false
Console.WriteLine(str.Equals(str1));  // true

我理解在这里工作的等号操作符,因为我们隐式地转换为对象,等号操作符正在检查两者的引用是否相等并返回false。

但我对第二个问题感到困惑,返回true看起来像是调用字符串类型提供的Equals override实现,如果它们相等,它会检查字符串的内容。

我的问题是,为什么它也不检查运算符的内容平等性,它们的实际类型是string而不是object。正当

而下面的代码为两者输出ture:

object str = "test";
object str1 = "test";
Console.WriteLine(str==str1); // true
Console.WriteLine(str.Equals(str1)); // true

共有3个答案

施赞
2023-03-14

这是因为字符串实习;当你写作时:

object str = "test";
html" target="_blank">object str1 = "test";
Console.WriteLine(str==str1);

正如预期的那样,编译器会在内部将两个字符串以静默方式复制到一个位置,这样两个指针实际上会指向同一个对象。

如果你从一个字符数组中创建一个字符串,那么编译器就不足以理解你的意图,而且它与上面的方法是等价的,因此,作为一个字符串和一个引用类型,它们实际上是内存中两个不同的对象。

看看这篇文章:https://blogs.msdn.microsoft.com/ericlippert/2009/09/28/string-interning-and-string-empty/

Equals方法在字符串中被重写,因此它比较的是字符串的实际内容,而不是在您的情况下作为==(参考Equals)的地址,因为类型是对象。

韦宣
2023-03-14

当==用于object类型的表达式时,它将解析为System。对象引用等于。

Equals只是一个虚拟方法,其行为也是如此,因此将使用重写的版本(对于字符串类型,该版本比较内容)。

辛弘壮
2023-03-14

与:

Console.WriteLine(str==str1); // false

编译时确定要使用操作符==的哪个C#预定义(正式)重载。由于strstr1被声明为对象,重载操作符==(对象,对象)被选择。这在编译时是固定的。只是因为实际的运行时类型碰巧更具体,这不会改变。如果您希望在运行时绑定,请使用控制台。WriteLine(((动态)str==(动态)str1);/*true*/代替。

与:

Console.WriteLine(str.Equals(str1));  // true

对象上调用虚拟方法。虚拟意味着它将转到运行时相关的覆盖。类系统。字符串有一个覆盖,并且因为str将具有运行时类型System。字符串,覆盖将由“虚拟调度”使用。

关于问题末尾的补充:由于字符串实习,情况有所不同。String interning是一种优化,其中相同的物理实例用于值相同的形式上不同的字符串。当源代码中给出了两个字符串的值时,string interning将“优化”并对同一实例进行两次引用。这通常是无害的,因为字符串保证是不可变的。因此,通常情况下,您不关心它是同一个实例还是具有相同值的另一个实例。但在你的例子中,我们可以“揭示”实习。

注:字符串实习与您最初的问题无关。只有在你的问题中添加了一个新的例子之后,字符串实习才变得有意义。

 类似资料:
  • 我有两个向量: 我试图使用比较它们。不幸的是,给出了一个意想不到的结果。 虽然我希望: 那么,这是什么原因造成的呢?怎样才能达到预期的效果呢? 这个问题似乎与这样一个事实有关,即两个向量的最后一个元素与将更改为例如确实给出了预期的结果相同,并且还因为将设置为给出而不是。 编辑 换句话说,我希望丢失的元素(当长度不同时)作为零传递(只有似乎给出

  • 我创建了的两个实例,如下所示。一个是从创建的,另一个是相同的,但在开头加上了一些附加的数字。使用方法比较它们时,它返回: 我认为添加的数字被丢弃了,并且两者给出了相同的UUID字符串值。为什么会这样?

  • 问题内容: 好的,这很愚蠢,但是wtf还在继续吗? 我在Servlet中有一个String变量,它接受参数的值,并基于该值进行测试以执行某些操作,但是该方法不起作用。问题是什么? 在控制台上,System.out.println向我显示了动作的价值是“某物” 问题答案: 您的第二个比较是错误的。您还应该使用代替,例如: 该运算符比较 引用 的(字符串)对象和正常情况下 等于 字符串不自动具有相同的

  • 问题内容: 我有一个Android应用程序,我想检查安装的应用程序名称是否与传递给包含此代码的函数的字符串匹配。代码和示例如下: 假设您打过电话,并且手机上的应用程序名称与返回的名称相同。但是,它永远不会。我记录了结果,它应该匹配,但事实并非如此。任何人都可以请问我为什么这行不通吗? 问题答案: 使用String的equals()方法代替==运算符来比较字符串: 在Java中,新手遇到的最常见错误

  • 问题内容: 字符串部分是: 但是当我与: 以上结果为假, 我很困惑,所以有人可以告诉我为什么吗? 问题答案: 该==运营商比较对象引用,在不值秒。 要比较 的值,请使用以下方法: Java中的任何其他对象都是如此-比较值时,请始终使用equals方法而不是使用==运算符。 该方法是的一部分,并且应被将以一种或另一种方式进行比较的类覆盖。

  • 问题内容: 我从书中看到以下代码: 但没有提到为什么“一个”大于“四个”。我试过了,它小于a和b。我想知道JavaScript如何比较这些字符串。 问题答案: 因为和许多编程语言一样,字符串是按字典顺序进行比较的。 你可以认为这是一个空想家版本的字母顺序,区别在于字母排序仅覆盖了26个字符通过。