This is the first of a weekly three part serie of posts about Nullable<T>. In these posts I want to describe the reasons behind three design choices:
1. Why not just use SQL semantics for null?
2. Why null == null doesn't imply null >= null and null <= null?
3. Why inside a generic class with a type parameter t the expression t == null will return false, when t is a nullable type and the value of it is null.
Let's start from the first question as the answer is shorter. We'll get to the other two in the coming weeks.
The first question relates to the reason not to have the same semantics as SQL for relational operators. The SQL semantics have been commonly referred to as three-value logic where null == null returns null. Introducing such logic in the C# language would be problematic. The main reason is that the language already contains the concept of null for reference types and it does have the programming languages traditional two-value logic where null == null returns true.
Granted that we cannot change this definition, then the addition of three-value logic just for some types would be confusing. We would need, for example, to create a new NullableString class to be able to apply three-value logic operators to it. More generally, the presence in the same code of two value logic and three value logic operators would make the code quite difficult to write, read and maintain.