The behaviour described below is specific to .net-3.5 only
I just ran across the most astonishing behavior in the C# compiler;
I
Of course this is not only an issue for Guid
. The same behavior is seen with any struct
type which is not a pre-defined type of C# provided that the struct
overloads operator ==
in the usual way. Other examples in the framework include DateTime
and TimeSpan
.
This deserves a compile-time warning since, while technically legal because of the lifted operator, this is not a useful comparison since it always gives false
. As such, it is an indication of a programmer mistake.
As Eric Lippert said in his answer, the compile-time warning existed with the Visual C# 2.0 compiler. In versions 3.0 through 5.0, the warning was accidentally omitted (for these "user-defined" struct
types, but not for pre-defined value types like int
, and not for enum types).
Since C# 6.0 (based on Roslyn), the compiler detects this code problem once again. However, because of backwards compatibility(?!), the warning is not issued unless you compile your code with the so-called strict feature.
To enable strict when you use a .csproj
file (most usual case), unload the project from Visual Studio, edit the file, insert the XML element:
<Features>strict</Features>
into each <PropertyGroup>
(there will usually be more than one) of the .csproj
file. You then get the warning (can be "promoted" to an error if you use Treat warnings as errors).
If you cannot edit the .csproj
and if you call msbuild.exe
from the command line for compiling, use the switch:
/p:Features=strict
to msbuild.exe
.
If you do not use .csproj
files because you compile directly with csc.exe
(the C# compiler), use the switch:
/features:strict
to csc.exe
on the command line.
The comparison is valid because the compiler converts the Guid
to a Nullable<Guid>
and then it makes sense.
There is a bug report on the warning not being issued here.
See here here for a fuller explanation from Eric Lippert.
Mark is correct. Value types that define their own equality operators automatically get lifted-to-nullable versions defined as well, for free. The nullable equality operator that takes two nullable guids is applicable in this situation, will be called, and will always return false.
In C# 2, this produced a warning, but for some reason, this stopped producing a warning for guid-to-null but continues to produce a warning for int-to-null. I don't know why; I haven't had time to investigate yet.
I apologize for the error; I probably screwed up one of the warning-detection code paths when rewriting the nullable logic in C# 3. The addition of expression trees to the language majorly changed the order in which nullable arithmetic operations are realized; I made numerous mistakes moving that code around. It's some complicated code.
Actually there is a case when Guild == null will return true.
However it is kinda hard to explain.
In ORM mapping frameworks (openAccess for example) when you have a Guid field which will have a default value of Guid.Empty of course it is possible to have the fallowing scenario :
In short (using OpenAccess but probably not only) :
var item = GetItems().Where(i => i.SomeGuidField == null); will work and u will get items with null guid this is after an schema update. item.First().SomeGuidField will return Empty Guid
var item = GetItems().Where(i => i.SomeGuidField == Guid.Empty); will not work even if after the population of the item it will be Guid.Empty and will return empty result.