You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A sub-heading of the issue could be: reference type vs. value type vs. nullable (value/reference?) type
Basic problem: in a generic class with unconstrained T, for some T x, x == null is NOT always false for value types: when T is nullable value type, it depends on the HasValue property!
The current publicly searchable specification (C#6 draft) differs from C#5 (final spec) and (most probably) the compiler/JIT reality.
It's quite unfortunate the C#6 draft still contains error comming from the original MS C#5 spec, which were corrected in the finalized/ECMA C#5 spec.
Refers to dotnet/docs#8251 (I read it while being half-way through writing this issue 🙄... After googling "C# language specification", going on the end of the page, finding "Formal C# Language Specification" issue 😢)
...
The predefined reference type equality operators require one of the following:
Both operands are a value of a type known to be a reference_type or the literal null. Furthermore, an explicit reference conversion (Explicit reference conversions) exists from the type of either operand to the type of the other operand.
One operand is a value of type T where T is a type_parameter and the other operand is the literal null. Furthermore T does not have the value type constraint.
...
Notable implications of these rules are:
...
If an operand of a type parameter type T is compared to null, and the run-time type of T is a value type, the result of the comparison is false.
...
The following example checks whether an argument of an unconstrained type parameter type is null.
12.11.7 Reference type equality operators
...
• Both operands are a value of a type known to be a reference-type or the literal null. Furthermore, an
explicit identity or reference conversion (§11.3.5) exists from either operand to the type of the other
operand.
• One operand is the literal null, and the other operand is a value of type T where T is a typeparameter that is not known to be a value type, and does not have the value type constraint.
o If at runtime T is a non-nullable value type, the result of == is false and the result of != is true.
o If at runtime T is a nullable value type, the result is computed from the HasValue property of the
operand, as described in (§12.11.10).
o If at runtime T is a reference type, the result is true if the operand is null, and false otherwise.
...
[Example: The following example checks whether an argument of an unconstrained type parameter type is null. same code here
The x == null construct is permitted even though T could represent a non-nullable value type, and the result is simply defined to be false when T is a non-nullable value type. end example]
There are more differences between C#5 and C#6 draft in these sections, for example C#5 spec "guarantees" that no boxing occurs:
Operands of predefined reference type equality operators are never boxed.
=============
Note: There is also a section about [Nullable] == null in the spec, and that one is the same in both. This section does not apply to the problem, it only applies when the expression is (known to be) of a nullable type.
C#6 draft
C#5: 12.11.10 Equality operators between nullable value types and the null literal
Edit: removed the citation of "Equality operators and null" / "12.11.10 Equality operators between nullable value types and the null literal" sections as they are not vital to the issue.
Edit #2: I made the important parts of citations bold and the introduction of issues more clear.
The text was updated successfully, but these errors were encountered:
where x is an expression of a nullable type, if operator overload resolution (Binary operator overload resolution) fails to find an applicable operator, the result is instead computed from the HasValue property of x. Specifically, the first two forms are translated into !x.HasValue, and last two forms are translated into x.HasValue.
@bbarry Yes, that makes the Equality operators and null / 12.11.10 Equality operators between nullable value types and the null literal of the respective specs not apply to the generic case. The issue stems from the (12.11.7) Reference type equality operators. I will make an edit/add note to the issue.
A sub-heading of the issue could be: reference type vs. value type vs. nullable (value/reference?) type
Basic problem: in a generic class with unconstrained T, for some T x,
x == null
is NOT always false for value types: when T is nullable value type, it depends on the HasValue property!The current publicly searchable specification (C#6 draft) differs from C#5 (final spec) and (most probably) the compiler/JIT reality.
It's quite unfortunate the C#6 draft still contains error comming from the original MS C#5 spec, which were corrected in the finalized/ECMA C#5 spec.
Refers to dotnet/docs#8251 (I read it while being half-way through writing this issue 🙄... After googling "C# language specification", going on the end of the page, finding "Formal C# Language Specification" issue 😢)
The "current public spec" https://github.com/dotnet/csharplang/blob/892af9016b/spec/expressions.md#reference-type-equality-operators (current version) being fed into
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#reference-type-equality-operators
which claims to be draft of C#6 spec, says:
While the C#5 spec says:
There are more differences between C#5 and C#6 draft in these sections, for example C#5 spec "guarantees" that no boxing occurs:
=============
Note: There is also a section about [Nullable] == null in the spec, and that one is the same in both. This section does not apply to the problem, it only applies when the expression is (known to be) of a nullable type.
C#6 draft
C#5: 12.11.10 Equality operators between nullable value types and the null literal
Edit: removed the citation of "Equality operators and null" / "12.11.10 Equality operators between nullable value types and the null literal" sections as they are not vital to the issue.
Edit #2: I made the important parts of citations bold and the introduction of issues more clear.
The text was updated successfully, but these errors were encountered: