【问题标题】:C# Difference of output between char return method and object return methodC#char返回方法和对象返回方法输出的区别
【发布时间】:2017-01-29 15:41:24
【问题描述】:

我在解决挑战测试时遇到了小问题,我正在比较输出

private object PopS() {
   return stack.Pop();
}

private object DequeueQ() {
   return queue.Dequeue();
}

对于回文词。

声明:

if(PopS() != DequeueQ()) isPalindrome = false;

我在这个 IF 语句上设置了断点,作为输入回文词“aaaaa”提供,但是尽管 Locals 窗口显示 Pop() 返回 97 'a' 并且 DequeueQ() 返回 97 'a',语句被认为是“不等于”。

当我将方法转换从对象更改为字符时,它起作用了。 Locals 中的输出是相同的。

有人可以解释一下这种行为吗?现在试图理解为什么来自“object”转换的 2 个相同的返回不相等,而来自“char”转换的 2 个相同的返回是相等的。

非常感谢, 迈克尔。

【问题讨论】:

    标签: c# object methods char


    【解决方案1】:

    这被称为“拳击”。

    您可能知道,当== 运算符用于没有重载== 的引用类型时,它会比较引用是否相同。另一方面,当与值类型一起使用时,它会比较值。

    这两个chars 最初是值类型,这就是为什么将方法更改为返回char 使其工作。 'a''a' 的值相等。

    但是方法的返回类型都是objectobject 是一个引用类型。所以在运行时,这两个chars 需要成为一个引用类型。这被称为装箱。每个char 都被装箱,因此有两个单独的对象,都包含值'a'。但由于它们是引用类型,== 会检查它们是否是同一个对象,显然它们不是。因此,== 的计算结果为 false

    【讨论】:

      【解决方案2】:

      这与类和Equals(object o)(覆盖operator ==)方法有关。字符定义如下:

      public class char : object
      {
          private uint value;
      
          //some more implementation
      
          override bool Equals(object o)
          {
              //code simplified - no try-catches etc.
              return this.value.Equals((uint) o);
          }
      }
      

      现在,当您尝试比较 object 类型的对象时,它们没有覆盖此 Equals 方法并使用默认方法。由于对象是默认引用类型,它们试图比较引用。

      更多详情请关注MSDN

      另外MSDN - Class and struct differences会给你一些更多的信息。

      你的代码是做什么的?

      它从一侧取“a”,从另一侧取“a”。它将创建每个(对象)的新实例,例如:

      char obj1 = 'a';
      char obj2 = 'a';
      

      如果您将它们作为字符进行比较,您将获得真正的价值:

      obj1.Equals(obj2); //true
      

      但是如果你把它们扔给对象,Equals 的内部实现将检查内存(PC 的物理内存)并查看 obj1 的实例在哪里以及 obj2 的实例在哪里。如果他们没有在同一个位置找到两者(相同的内存地址 - 内存中的相同单元格,它将返回 false)

      ((object)obj1).Equals(obj2); // false
      ((object)obj1).Equals((object)obj2); // false
      (obj1).Equals((object)obj2); // false
      

      这可以通过在调用 Equals 方法之前强制转换变量来避免。

      ((char)(object)obj1).Equals(obj2); // true
      ((char)(object)obj1).Equals((char)(object)obj2); // true
      (obj1).Equals((char)(object)obj2); // true
      

      它如何与引用相等一起工作?

      public class MyClass
      {
          public char Val { get; set; }
      }
      
      MyClass obj1 = new MyClass() { Val = 'a' };
      MyClass obj2 = obj1;
      obj1.Equals(obj2); // true
      

      **注意:** 我没有像@Sweeper 那样使用术语“拳击”。

      装箱意味着对象被转换为不同的对象,并获得与作为其他对象处理相关的不同行为。 (它与 OOP 术语多态性密切相关)。

      【讨论】:

        猜你喜欢
        • 2018-01-07
        • 2015-12-30
        • 1970-01-01
        • 2015-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多