Ho letto la specifica del linguaggio C # sugli operatori logici condizionali ||
e &&
, noti anche come operatori logici di cortocircuito. A me sembrava poco chiaro se questi esistessero per booleani nullable, ovvero il tipo di operando Nullable<bool>
(anche scritto bool?
), quindi l'ho provato con la digitazione non dinamica:
bool a = true;
bool? b = null;
bool? xxxx = b || a; // compile-time error, || can't be applied to these types
Questo sembrava risolvere la questione (non riuscivo a capire chiaramente le specifiche, ma supponendo che l'implementazione del compilatore Visual C # fosse corretta, ora lo sapevo).
Tuttavia, volevo provare anche con l' dynamic
associazione. Quindi ho provato questo invece:
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);
}
}
Il risultato sorprendente è che questo funziona senza eccezioni.
Ebbene, x
e y
non sorprende, le loro dichiarazioni portano al recupero di entrambe le proprietà e i valori risultanti sono come previsto, x
è true
ed y
è null
.
Ma la valutazione di xx
of non ha A || B
portato a nessuna eccezione di tempo di associazione, e solo la proprietà è A
stata letta, no B
. Perché succede questo? Come puoi vedere, potremmo cambiare il B
getter per restituire un oggetto pazzo, come "Hello world"
, e xx
lo valuteremmo comunque true
senza problemi di binding ...
Anche la valutazione A && B
(per yy
) non porta a nessun errore di tempo di associazione. E qui vengono recuperate entrambe le proprietà, ovviamente. Perché ciò è consentito dal raccoglitore di runtime? Se l'oggetto restituito da B
viene modificato in un oggetto "cattivo" (come un string
), si verifica un'eccezione di associazione.
È questo comportamento corretto? (Come puoi dedurlo dalle specifiche?)
Se provi B
come primo operando, entrambi B || A
e B && A
danno un'eccezione al binder di runtime ( B | A
e B & A
funzionano bene poiché tutto è normale con operatori non in cortocircuito |
e &
).
(Provato con il compilatore C # di Visual Studio 2013 e la versione runtime .NET 4.5.2.)
Nullable<Boolean>
coinvolto, solo booleani in scatola trattati comedynamic
- il tuo test conbool?
è irrilevante. (Ovviamente, questa non è una risposta completa, solo il germe di una.)