¿Por qué las estructuras genéricas y no genéricas se tratan de manera diferente cuando se construye una expresión que hace que el operador == sea anulable?
Esto parece un error al levantar a cero los operandos en estructuras genéricas.
Considere la siguiente estructura ficticia, que anulaoperator==
:
struct MyStruct
{
private readonly int _value;
public MyStruct(int val) { this._value = val; }
public override bool Equals(object obj) { return false; }
public override int GetHashCode() { return base.GetHashCode(); }
public static bool operator ==(MyStruct a, MyStruct b) { return false; }
public static bool operator !=(MyStruct a, MyStruct b) { return false; }
}
Ahora considera las siguientes expresiones:
Expression<Func<MyStruct, MyStruct, bool>> exprA =
(valueA, valueB) => valueA == valueB;
Expression<Func<MyStruct?, MyStruct?, bool>> exprB =
(nullableValueA, nullableValueB) => nullableValueA == nullableValueB;
Expression<Func<MyStruct?, MyStruct, bool>> exprC =
(nullableValueA, valueB) => nullableValueA == valueB;
Los tres compilan y corren como se espera.
Cuando están compilados (usando.Compile()
) producen el siguiente código (parafraseado al inglés de la IL):
La primera expresión que lleva soloMyStruct
(no anulables) argumentos, simplemente llamadasop_Equality
(nuestra implementación deoperator ==
)
La segunda expresión, cuando se compila, produce un código que verifica cada argumento para ver siHasValue
. Si ambos no lo hacen (ambos son iguales)null
), devolucionestrue
. Si solo uno tiene un valor, devuelvefalse
. De lo contrario, llamadasop_Equality
en los dos valores.
La tercera expresión comprueba el argumento anulable para ver si tiene un valor; si no, devuelve falso. De lo contrario, llamadasop_Equality
.
Hasta ahora tan bueno.
Siguiente paso: hacer exactamente lo mismo con un tipo genérico - cambiarMyStruct
aMyStruct<T>
En todas partes en la definición del tipo, y cambiarlo aMyStruct<int>
en las expresiones.
Ahora la tercera expresión compila pero lanza una excepción de tiempo de ejecuciónInvalidOperationException
con el siguiente mensaje:
Los operandos para el operador 'Igual' no coinciden con los parámetros del método 'op_Equality'.
Yo esperaría que las estructuras genéricas se comporten exactamente igual que las no genéricas, con todo el levantamiento de nulos descrito anteriormente.
Así que mis preguntas son:
¿Por qué hay una diferencia entre estructuras genéricas y no genéricas?¿Cuál es el significado de esta excepción?¿Es este un error en C # / .NET?El código completo para reproducir esto esdisponible en esta esencia.