La soluzione al Quiz Sharp #61 mi sembra abbastanza interessante per meritare un post a parte (nomi come Miguel de Icaza, Jon Skeet, Abhinaba Basu, hanno considerato strano il comportamento del compilatore C# 2.0 nel comparare i valori value type a null)
La risposta corretta al quiz e' che eseguendo lo snippet si ottiene un'eccezione a runtime (StackOverflowException). Vediamo di seguito il perche', con le specifiche in mano:
Per evaluare l'espressione value != null nell'implementazione dell'operatore, dove value e' un not-nullable value type, il compilatore applica alcune conversioni. Per esempio, per ogni nullable type, esiste una conversione implicita dal tipo null al tipo nullable (ECMA-334, 13.7.1). Inoltre, una volta definito l'operatore di conversione implicita da Foo a bool, in cui sia Foo che bool sono not-nullable value types, esistono automaticamente anche le conversioni nullable (ECMA-334, 13.7.2) implicite da Foo? a bool? e da Foo a bool? e la conversione esplicita da Foo? a bool. Quest'ultima non ci interessa perche' e' esplicita. Ci interessa invece quella da Foo a bool? perche', in questo modo, la comparazione a null nell'espressione si farebbe tra due nullable types (bool? entrambi). Su come si applica la nullable conversion da Foo a bool?, c'e' scritto nelle specifiche (13.7.2): "If the nullable conversion is from S to T?, the conversion is evaluated as the underlying conversion from S to T followed by a wrapping from T to T?", quindi prima si applica la conversione sottostante, da Foo a bool, seguita poi da quella da bool a bool?. Ma quella da Foo a bool e' proprio la conversione implicita che stiamo implementando, percio' siamo nella ricorsione che ci porta alla StackOverflowException... Tra l'altro, il compilatore C# ci avverte con il warning CS0472: "The result of the expression is always 'true' since a value of type 'bool' is never equal to 'null' of type 'bool?'", quindi "null of type bool?" perche' e' gia' stata identificata la conversione nullable.
Per chi vuole spulciare nel codice di SSCLI 2.0, da guardare FUNCBREC::BindNubEqOpCore nel file "operators.cpp".