vb.net 为什么 C# 无法相互比较两种对象类型,而 VB 却没有?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14837209/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why C# fails to compare two object types with each other but VB doesn't?
提问by Mohsen Sarkar
I have two objects in C# and don't know if it's Boolean or any other type. However when I try to compare those C# fails to give the right answer. I have tried the same code with VB.NET and that did it !
我在 C# 中有两个对象,不知道它是布尔类型还是任何其他类型。但是,当我尝试比较那些 C# 时未能给出正确答案。我已经在 VB.NET 中尝试了相同的代码,并且成功了!
Can anyone tell me how to fix this if there is a solution ?
如果有解决方案,谁能告诉我如何解决这个问题?
C#:
C#:
object a = true;
object b = true;
object c = false;
if (a == b) c = true;
MessageBox.Show(c.ToString()); //Outputs False !!
VB.NET:
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
回答by Jon Skeet
In C#, the ==operator (when applied to reference type expressions) performs a referenceequality check unless it's overloaded. You're comparing two references which are the result of boxing conversions, so those are distinct references.
在 C# 中,==运算符(当应用于引用类型表达式时)执行引用相等性检查,除非它被重载。您正在比较两个作为装箱转换结果的引用,因此它们是不同的引用。
EDIT: With types which overload the ==, you can get different behaviour - but that's based on the compile-timetype of the expressions. For example, stringprovides ==(string, string):
编辑:对于重载 的类型==,您可以获得不同的行为 - 但这是基于表达式的编译时类型。例如,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
Here the first comparison is using the overloaded operator, but the second is using the "default" reference comparison.
这里第一个比较使用重载运算符,但第二个使用“默认”引用比较。
In VB, the =operator does a whole lot more work - it's not even just equivalent to using object.Equals(x, y), as things like Option Comparecan affect how text is compared.
在 VB 中,=操作符做了更多的工作——它甚至不仅仅等同于使用object.Equals(x, y),因为诸如此类的东西Option Compare会影响文本的比较方式。
Fundamentally the operators don't work the same way and aren't intendedto work the same way.
从根本上讲,操作符的工作方式不同,也不打算以相同的方式工作。
回答by Konrad Rudolph
In addition to Jon's answer which explains the C# side of things, here's what VB does:
除了解释 C# 方面的 Jon 的回答之外,以下是 VB 的作用:
In VB with Option Strict On, a comparison via =alwaystests for value equality and never for reference equality. In fact, your code doesn't even compile once you switch Option Strict Onbecause System.Objectdoesn't define an Operator=. You should alwayshave this option on, it catches bugs more effectively than a venus flytrap (although in your particular case this lax behaviour actually does the right thing).1
在 VB 中Option Strict On,通过=始终测试值相等而从不测试引用相等的比较。事实上,一旦你切换,你的代码甚至不会编译,Option Strict On因为System.Object没有定义Operator=. 您应该始终启用此选项,它比捕蝇草更有效地捕获错误(尽管在您的特定情况下,这种松散的行为实际上是正确的)。1
In fact, with Option Strict On, VB behaves even stricter than C#: In C#, a == beithertriggers a call to SomeType.operator==(a, b)or, if this doesn't exist, invokes reference equality comparison (which is equivalent to calling object.ReferenceEquals(a, b)).
事实上,对于Option Strict On,VB 的行为甚至比 C# 更严格:在 C# 中,a == b要么触发对 的调用,要么SomeType.operator==(a, b)在不存在的情况下调用引用相等比较(相当于调用object.ReferenceEquals(a, b))。
In VB on the other hand, the comparison a = balwaysinvokes the equality operator.2If you want to use reference equality comparison, you have to use a Is b(which is, once again, the same as Object.ReferenceEquals(a, b)).
另一方面,在 VB 中,比较a = b总是调用相等运算符。2如果要使用引用相等比较,则必须使用a Is b(再次与 相同Object.ReferenceEquals(a, b))。
1)Here's a good indication why using Option Strict Offis a bad idea: I've used VB.NET for almost a decade, from before .NET's official release until a few years ago, and I've absolutely no ideawhat a = bdoes with Option Strict Off. It does some kind of equality comparison, but what exactly happens and why, no idea. It's more complex than C#'s dynamicfeature, though (because that relies on a well-documented API). Here's what the MSDN says:
1)这也是为什么使用一个很好的迹象Option Strict Off是一个坏主意:我用VB.NET了近十年,从.NET的正式发布之前,直到几年以前,我已经完全不知道有什么a = b用呢Option Strict Off。它进行某种平等比较,但究竟发生了什么以及为什么,不知道。不过,它比 C# 的dynamic功能更复杂(因为它依赖于一个有据可查的 API)。这是 MSDN 所说的:
Because
Option Strict Onprovides strong typing, prevents unintended type conversions with data loss, disallows late binding, and improves performance, its use is strongly recommended.
因为
Option Strict On提供了强类型,防止意外的类型转换和数据丢失,不允许后期绑定,并提高性能,强烈推荐使用它。
2)Jon has mentioned one exception, strings, where equality comparison does some more things for reasons of backwards compatibility.
2)Jon 提到了一个例外,字符串,出于向后兼容性的原因,相等比较做了更多的事情。
回答by Lobo
Object instances are not compared with the operator "==". You should to use method "equals". With "==" operator are comparing references, not objects.
对象实例不与运算符“==”进行比较。您应该使用“equals”方法。使用“==”运算符比较引用,而不是对象。
Try this:
尝试这个:
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");
}
Results:
结果:
a reference is not equal to b reference
a object is not equal to b object
Now, try this:
现在,试试这个:
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");
}
Results:
结果:
a reference is not equal to b reference
a object is equal to b object
回答by Servy
The issue is that the == operator in C# is a call to a static method (well, maybe not technically, but it can be though of as such) based on the compile time typeof the two parameters. What the actual runtime types of those objects are doesn't matter.
问题是 C# 中的 == 运算符是对基于两个参数的编译时类型的静态方法的调用(好吧,可能不是技术上的,但可以这样认为)。这些对象的实际运行时类型是什么并不重要。
Based on that compile time type the compiler will determine what implementation of operator ==to use. It might use the default objectimplementation, it might use one of the numeric overloads provided by the language, or it could be a user defined implementation.
根据该编译时类型,编译器将确定operator ==要使用的实现。它可能使用默认object实现,可能使用该语言提供的数字重载之一,也可能是用户定义的实现。
This is different from VB in that VB doesn't determine the implementation at compile time. It waits until runtime and inspects the two parameters that it is given to determine which implementation of the ==operator it should use.
这与 VB 的不同之处在于 VB 在编译时不确定实现。它一直等到运行时并检查给定的两个参数,以确定==它应该使用运算符的哪个实现。
Your code contains boolean values, but they are in variables that are of type object. Because the variableis of type object, the C# compiler use the objectimplementation of ==, which compares the references, not the object instances. Since the boolean values are boxes, they don't have the same reference, even though their values are the same.
您的代码包含布尔值,但它们位于类型为 的变量中object。由于变量是 类型object,C# 编译器使用 的object实现==,它比较引用,而不是对象实例。由于布尔值是盒子,它们没有相同的引用,即使它们的值相同。
The VB code doesn't care what type the variable is. It waits until runtime and then checks the two variables, sees that they are actuallyof both of type boolean, and so uses the boolean ==operator implementation. That implementation compares the values of the booleans, not their references (and the booleans will be unboxed before calling calling that operator, so a reference comparison doesn't even make sense any more). Because the values of the booleans are the same, it returns true.
VB 代码并不关心变量是什么类型。它等到运行时,然后检查两个变量,发现它们实际上都是布尔类型,因此使用布尔==运算符实现。该实现比较布尔值的值,而不是它们的引用(在调用该运算符之前,布尔值将被拆箱,因此引用比较甚至不再有意义)。因为布尔值是相同的,所以它返回真。

