Operadores de curto-circuito || e && existem para booleanos anuláveis? O RuntimeBinder às vezes pensa assim
Eu li a Especificação da linguagem C # noOperadores lógicos condicionais ||
e&&
, também conhecidos como operadores lógicos em curto-circuito. Para mim, não parecia claro se existiam para booleanos anuláveis, ou seja, o tipo de operandoNullable<bool>
(também escritobool?
), então tentei com digitação não dinâmica:
bool a = true;
bool? b = null;
bool? xxxx = b || a; // compile-time error, || can't be applied to these types
Isso pareceu resolver a questão (não consegui entender claramente a especificação, mas assumindo que a implementação do compilador Visual C # estava correta, agora eu sabia).
No entanto, eu queria tentar comdynamic
obrigatório também. Então, eu tentei isso:
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);
}
}
O resultado surpreendente é que isso ocorre sem exceção.
Bem,x
ey
não são surpreendentes, suas declarações levam a que ambas as propriedades sejam recuperadas e os valores resultantes são os esperados,x
étrue
ey
énull
.
Mas a avaliação paraxx
doA || B
levar a nenhuma exceção de tempo de ligação e apenas a propriedadeA
foi lido, nãoB
. Por que isso acontece? Como você pode ver, podemos mudar oB
getter para retornar um objeto louco, como"Hello world"
exx
ainda avaliariatrue
sem problemas de ligação ...
AvaliandoA && B
(parayy
) também leva a nenhum erro no tempo de ligação. E aqui as duas propriedades são recuperadas, é claro. Por que isso é permitido pelo fichário de tempo de execução? Se o objeto retornado deB
é alterado para um objeto "ruim" (como umstring
), ocorre uma exceção de ligação.
Esse comportamento é correto? (Como você pode inferir isso das especificações?)
Se você tentarB
como primeiro operando, ambosB || A
eB && A
dar exceção do fichário de tempo de execução (B | A
eB & A
funciona bem, pois tudo é normal com operadores sem curto-circuito|
e&
)
(Tentei com o compilador C # do Visual Studio 2013 e a versão de tempo de execução .NET 4.5.2.)