una - ¿Por qué C#no puede comparar dos tipos de objetos entre sí, pero VB no lo hace?
equals c# ejemplos (4)
Tengo dos objetos en C # y no sé si es booleano o de otro tipo. Sin embargo, cuando trato de comparar esos C # no da la respuesta correcta. ¡He intentado el mismo código con VB.NET y eso fue todo!
¿Alguien puede decirme cómo solucionar esto si hay una solución?
DO#:
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
Además de la respuesta de Jon que explica el lado C # de las cosas, esto es lo que hace VB:
En VB con Option Strict On
, una comparación via =
siempre prueba la igualdad de valor y nunca la igualdad de referencia. De hecho, su código ni siquiera se compila una vez que activa Option Strict On
porque System.Object
no define un Operator=
. Siempre debes tener esta opción activada, atrapa los errores de forma más efectiva que un venus flytrap (aunque en tu caso particular, este comportamiento laxo realmente hace lo correcto). 1
De hecho, con Option Strict On
, VB se comporta incluso más estrictamente que C #: en C #, a == b
activa una llamada a SomeType.operator==(a, b)
o, si no existe, invoca una comparación de igualdad de referencia (que es equivalente a invocar object.ReferenceEquals(a, b)
).
En VB, por otro lado, la comparación a = b
siempre invoca al operador de igualdad. 2 Si desea utilizar la comparación de igualdad de referencia, debe usar a Is b
(que es, una vez más, el mismo que Object.ReferenceEquals(a, b)
).
1) Aquí hay una buena indicación de por qué usar Option Strict Off
es una mala idea: he usado VB.NET durante casi una década, desde el lanzamiento oficial de .NET hasta hace unos años, y no tengo ni idea de qué a = b
hace con Option Strict Off
. Hace algún tipo de comparación de igualdad, pero qué sucede exactamente y por qué, ni idea. Sin embargo, es más complejo que dynamic
característica dynamic
de C # (porque se basa en una API bien documentada). Esto es lo que dice MSDN:
Debido a que
Option Strict On
proporciona un tipado sólido , evita las conversiones involuntarias de tipo con la pérdida de datos, no permite la vinculación tardía y mejora el rendimiento, se recomienda encarecidamente su uso.
2) Jon ha mencionado una excepción, strings, donde la comparación de igualdad hace algunas cosas más por razones de compatibilidad con versiones anteriores.
El problema es que el operador == en C # es una llamada a un método estático (bueno, tal vez no técnicamente, pero puede considerarse como tal) en función del tipo de tiempo de compilación de los dos parámetros. Lo que son los tipos de tiempo de ejecución reales de esos objetos no importa.
En función de ese tipo de tiempo de compilación, el compilador determinará qué implementación de operator ==
usar. Podría usar la implementación de object
predeterminada, podría usar una de las sobrecargas numéricas provistas por el lenguaje, o podría ser una implementación definida por el usuario.
Esto es diferente de VB en que VB no determina la implementación en tiempo de compilación. Espera hasta el tiempo de ejecución e inspecciona los dos parámetros que se le dan para determinar qué implementación del operador ==
debería usar.
Su código contiene valores booleanos, pero están en variables que son de tipo object
. Como la variable es de tipo object
, el compilador de C # usa la implementación de object
de ==
, que compara las referencias , no las instancias de objeto. Como los valores booleanos son recuadros, no tienen la misma referencia, aunque sus valores sean los mismos.
Al código VB no le importa de qué tipo es la variable. Espera hasta el tiempo de ejecución y luego verifica las dos variables, ve que en realidad son de tipo booleano, y así usa la implementación del operador boolean ==
. Esa implementación compara los valores de los booleanos, no sus referencias (y los booleanos se desempaquetarán antes de llamar a ese operador, por lo que una comparación de referencia ya no tiene sentido). Como los valores de los booleanos son los mismos, devuelve verdadero.
En C #, el operador ==
(cuando se aplica a expresiones de tipo de referencia) realiza una verificación de igualdad de referencia a menos que esté sobrecargado . Está comparando dos referencias que son el resultado de las conversiones de boxeo, por lo que esas son referencias distintas.
EDITAR: con los tipos que sobrecargan el ==
, puede obtener un comportamiento diferente, pero eso se basa en el tipo de expresiones en tiempo de compilación . Por ejemplo, string
proporciona ==(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
Aquí la primera comparación es usar el operador sobrecargado, pero el segundo está usando la comparación de referencia "predeterminada".
En VB, el operador =
hace mucho más trabajo, ni siquiera equivale al uso de object.Equals(x, y)
, ya que Option Compare
como Option Compare
pueden afectar la comparación del texto.
Fundamentalmente, los operadores no funcionan de la misma manera y no están diseñados para funcionar de la misma manera.
Las instancias de objeto no se comparan con el operador "==". Deberías usar el método "igual". Con el operador "==" están comparando referencias, no objetos.
Prueba esto:
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");
}
Resultados:
a reference is not equal to b reference
a object is not equal to b object
Ahora, intenta esto:
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");
}
Resultados:
a reference is not equal to b reference
a object is equal to b object