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' dynamicassociazione. 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, xe ynon sorprende, le loro dichiarazioni portano al recupero di entrambe le proprietà e i valori risultanti sono come previsto, xè trueed yè null.
Ma la valutazione di xxof non ha A || Bportato a nessuna eccezione di tempo di associazione, e solo la proprietà è Astata letta, no B. Perché succede questo? Come puoi vedere, potremmo cambiare il Bgetter per restituire un oggetto pazzo, come "Hello world", e xxlo valuteremmo comunque truesenza 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 Bviene modificato in un oggetto "cattivo" (come un string), si verifica un'eccezione di associazione.
È questo comportamento corretto? (Come puoi dedurlo dalle specifiche?)
Se provi Bcome primo operando, entrambi B || Ae B && Adanno un'eccezione al binder di runtime ( B | Ae B & Afunzionano 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.)