Hacer operadores de cortocircuito || y && existen para booleanos anulables? The RuntimeBinder a veces piensa que sí
Leí la especificación del lenguaje C # en elOperadores lógicos condicionales ||
y&&
, también conocidos como operadores lógicos de cortocircuito. Para mí, no estaba claro si estos existían para booleanos anulables, es decir, el tipo de operandoNullable<bool>
(también escritobool?
), así que lo probé con la 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 podía entender la especificación claramente, pero suponiendo que la implementación del compilador de Visual C # era correcta, ahora lo sabía).
Sin embargo, quería probar condynamic
vinculante también. Así que intenté 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 se ejecuta sin excepción.
Bien,x
yy
no son sorprendentes, sus declaraciones conducen a la recuperación de ambas propiedades y los valores resultantes son los esperados,x
estrue
yy
esnull
.
Pero la evaluación paraxx
deA || B
no conducen a ninguna excepción de tiempo de enlace, y solo la propiedadA
fue leído, noB
. ¿Por qué pasó esto? Como puede ver, podríamos cambiar elB
getter para devolver un objeto loco, como"Hello world"
yxx
aún evaluaría atrue
sin problemas vinculantes ...
EvaluandoA && B
(parayy
) tampoco conduce a ningún error de tiempo de enlace. Y aquí se recuperan ambas propiedades, por supuesto. ¿Por qué está permitido por la carpeta de tiempo de ejecución? Si el objeto devuelto deB
se cambia a un objeto "malo" (como unstring
), se produce una excepción vinculante.
¿Es este el comportamiento correcto? (¿Cómo puedes inferir eso de la especificación?)
Si intentasB
como primer operando, ambosB || A
yB && A
dar excepción de carpeta de tiempo de ejecución (B | A
yB & A
funciona bien ya que todo es normal con operadores que no están en cortocircuito|
y&
)
(Probado con el compilador C # de Visual Studio 2013 y la versión de ejecución .NET 4.5.2.)