Leí la Especificación del lenguaje C # sobre los operadores lógicos condicionales ||
y &&
, también conocidos como operadores lógicos de cortocircuito. Para mí, no parecía claro si estos existían para valores booleanos que aceptan valores NULL, es decir, el tipo de operando Nullable<bool>
(también escrito bool?
), así que lo probé con escritura no dinámica:
bool a = true;
bool? b = null;
bool? xxxx = b || a; // compile-time error, || can't be applied to these types
Eso pareció resolver la pregunta (no pude entender la especificación claramente, pero suponiendo que la implementación del compilador de Visual C # fuera correcta, ahora lo sabía).
Sin embargo, también quería probar con la dynamic
encuadernación. Así que probé esto en su lugar:
static class Program
{
static dynamic A
{
get
{
Console.WriteLine("'A' evaluated");
return true;
}
}
static dynamic B
{
get
{
Console.WriteLine("'B' evaluated");
return null;
}
}
static void Main()
{
dynamic x = A | B;
Console.WriteLine((object)x);
dynamic y = A & B;
Console.WriteLine((object)y);
dynamic xx = A || B;
Console.WriteLine((object)xx);
dynamic yy = A && B;
Console.WriteLine((object)yy);
}
}
El resultado sorprendente es que esto funciona sin excepción.
Bueno, x
y y
no es de extrañar, sus declaraciones llevan a que se recuperen ambas propiedades, y los valores resultantes son los esperados, x
es true
y y
es null
.
Pero la evaluación xx
de no A || B
condujo a ninguna excepción de tiempo de vinculación, y solo A
se leyó la propiedad , no B
. ¿Por qué pasó esto? Como puede ver, podríamos cambiar el B
getter para devolver un objeto loco, como "Hello world"
, y xx
aún evaluaríamos true
sin problemas de vinculación ...
La evaluación A && B
(para yy
) tampoco conduce a ningún error de tiempo de vinculación. Y aquí se recuperan ambas propiedades, por supuesto. ¿Por qué lo permite el archivador en tiempo de ejecución? Si el objeto devuelto B
se cambia a un objeto "incorrecto" (como a string
), se produce una excepción de vinculación.
¿Es este el comportamiento correcto? (¿Cómo puedes inferir eso de la especificación?)
Si lo intenta B
como primer operando, ambos B || A
y B && A
dan una excepción del enlazador en tiempo de ejecución ( B | A
y B & A
funcionan bien, ya que todo es normal con operadores sin cortocircuito |
y &
).
(Probado con el compilador C # de Visual Studio 2013 y la versión en tiempo de ejecución .NET 4.5.2.)
Nullable<Boolean>
involucrados en absoluto, solo booleanos en caja tratados comodynamic
: su prueba conbool?
es irrelevante. (Por supuesto, esta no es una respuesta completa, solo el germen de una.)