我在C#中有两个对象,不知道它是布尔值还是其他任何类型。 但是,当我尝试比较那些C#未能给出正确的答案时。 我用VB.NET尝试了相同的代码并且做到了!
如果有解决方案,有人能告诉我如何解决这个问题吗?
C#:
object a = true;
object b = true;
object c = false;
if (a == b) c = true;
MessageBox.Show(c.ToString()); //Outputs False !!
VB.NET:
Dim a As Object = True
Dim b As Object = True
Dim c As Object = False
If (a = b) Then c = True
MessageBox.Show(c.ToString()) '// Outputs True
答案 0 :(得分:166)
在C#中,==
运算符(当应用于引用类型表达式时)执行引用等式检查,除非它重载。您正在比较两个引用是拳击转换的结果,因此这些是不同的引用。
编辑:对于使==
重载的类型,您可以获得不同的行为 - 但这是基于表达式的编译时类型。例如,string
提供==(string, string
):
string x = new string("foo".ToCharArray());
string y = new string("foo".ToCharArray());
Console.WriteLine(x == y); // True
Console.WriteLine((object) x == (object) y); // False
这里的第一个比较是使用重载运算符,但第二个是使用“默认”引用比较。
在VB中,=
运算符可以完成更多工作 - 它甚至不等同于使用object.Equals(x, y)
,因为Option Compare
之类的内容会影响文本的比较。
从根本上说,运营商的工作方式不同,并且意图以相同的方式工作。
答案 1 :(得分:79)
除了Jon的解释C#方面的答案之外,这是VB的作用:
在带有Option Strict On
的VB中,通过=
进行的比较总是测试值的相等性,从不测试引用相等性。实际上,由于Option Strict On
未定义System.Object
,因此切换Operator=
后,您的代码甚至无法编译。您应该始终启用此选项,它比金星捕蝇草更有效地捕获错误(尽管在您的特定情况下,这种松散的行为实际上做了正确的事情)。 1
事实上,对于Option Strict On
,VB的行为甚至比C#更严格:在C#中,a == b
要么会触发对SomeType.operator==(a, b)
的调用,或者如果这样做不存在,调用引用相等比较(相当于调用object.ReferenceEquals(a, b)
)。
另一方面,在VB中,比较a = b
总是调用相等运算符。 2 如果要使用引用相等比较,则必须使用a Is b
(再次,与Object.ReferenceEquals(a, b)
相同)。
1)这是一个很好的指示为什么使用Option Strict Off
是一个坏主意:我已经使用VB.NET近十年了,从.NET正式发布到几年之前以前,我完全不知道 a = b
对Option Strict Off
做了什么。它做了某种平等比较,但究竟发生了什么,为什么,不知道。它比C#的dynamic
功能更复杂(因为它依赖于记录良好的API)。 Here’s what the MSDN says:
由于
。Option Strict On
提供强类型,可防止数据丢失导致意外的类型转换,禁止后期绑定并提高性能,因此强烈建议使用
2) Jon提到了一个例外,字符串,其中为了向后兼容性,相等比较做了更多的事情。
答案 2 :(得分:4)
对象实例不与运算符“==”进行比较。你应该使用方法“等于”。使用“==”运算符比较引用,而不是对象。
试试这个:
public class MyObject
{
public MyObject(String v)
{
Value = v;
}
public String Value { get; set; }
}
MyObject a = new MyObject("a");
MyObject b = new MyObject("a");
if(a==b){
Debug.WriteLine("a reference is equal to b reference");
}else{
Debug.WriteLine("a reference is not equal to b reference");
}
if (a.Equals(b)) {
Debug.WriteLine("a object is equal to b object");
} else {
Debug.WriteLine("a object is not equal to b object");
}
结果:
a reference is not equal to b reference
a object is not equal to b object
现在,试试这个:
public class MyObject
{
public MyObject(String v)
{
Value = v;
}
public String Value { get; set; }
public bool Equals(MyObject o)
{
return (Value.CompareTo(o.Value)==0);
}
}
MyObject a = new MyObject("a");
MyObject b = new MyObject("a");
if(a==b){
Debug.WriteLine("a reference is equal to b reference");
}else{
Debug.WriteLine("a reference is not equal to b reference");
}
if (a.Equals(b)) {
Debug.WriteLine("a object is equal to b object");
} else {
Debug.WriteLine("a object is not equal to b object");
}
结果:
a reference is not equal to b reference
a object is equal to b object
答案 3 :(得分:3)
问题是C#中的==运算符是基于编译时类型的静态方法的调用(好吧,可能不是技术上的,但它可以是这样的)。这两个参数。这些对象的实际运行时类型并不重要。
基于该编译时类型,编译器将确定要使用的operator ==
的实现。它可能使用默认的object
实现,它可能使用该语言提供的一个数字重载,或者它可能是用户定义的实现。
这与VB的不同之处在于VB在编译时没有确定实现。它等待直到运行时并检查它给出的两个参数,以确定它应该使用的==
运算符的哪个实现。
您的代码包含布尔值,但它们位于object
类型的变量中。由于变量的类型为object
,因此C#编译器使用object
的{{1}}实现,它会比较引用,而不是对象实例。由于布尔值是方框,因此它们不具有相同的引用,即使它们的值相同。
VB代码并不关心变量的类型。它等到运行时,然后检查两个变量,发现它们都是实际上两种类型的boolean,因此使用布尔==
运算符实现。该实现比较布尔值,而不是它们的引用(并且在调用该运算符之前,布尔值将被取消装箱,因此参考比较甚至不再有意义)。因为布尔值相同,所以返回true。