我在解决挑战测试时遇到了一个小问题,我正在比较
的输出private object PopS() {
return stack.Pop();
}
和
private object DequeueQ() {
return queue.Dequeue();
}
为回文词。
Statment:
if(PopS() != DequeueQ()) isPalindrome = false;
我在这个IF声明上做了断点,作为输入回文词“aaaaa”提供,但是尽管Locals窗口显示Pop()返回97'a'而DequeueQ()返回97'a',但是认为两者都不等于”
当我将方法转换从对象更改为char时,它起作用了。本地人的输出是相同的。
有人能解释一下这种行为吗?试着理解为什么来自“对象”演员的两个相同的回报不相等而且来自“char”演员的2个相同的回报是相等的。
非常感谢, 迈克尔。
答案 0 :(得分:1)
这被称为“拳击”。
如您所知,当==
运算符用于没有重载==
的引用类型时,它会比较引用是否相同。另一方面,当与值类型一起使用时,它会比较值。
这两个char
最初是值类型,这就是为什么更改方法以返回char
会使其工作。 'a'
和'a'
的值相等。
但方法的返回类型都是object
。 object
是引用类型。因此,在运行时,两个char
需要成为引用类型。这被称为拳击。每个char
都装箱,因此有两个单独的对象,都包含值'a'
。但由于它们是引用类型,==
检查它们是否是同一个对象,它们显然不是。因此,==
评估为false
。
答案 1 :(得分:0)
此类适用于类和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术语多态性密切相关)。