Guid == null should not be allowed by the compiler

Possible duplicate:
C # ok with comparing value types with zero

The behavior described below is specific to .net-3.5 only

Hello,

I just ran into the most amazing behavior in the C # compiler,

I have the following code:

Guid g1 = Guid.Empty; bool b1= (g1 == null); 

Well, Guid is not NULL, so it can never be null . the comparison that I do in line 2 always returns false .

If you do the same for an integer, the compiler generates a warning saying that the result will always be false:

 int x=0; bool b2= (x==null); 

My question is: Why does the compiler allow comparing Guid with null ?
According to my information, he already knows that the result is always incorrect.
Is the inline conversion done so that the compiler is null is a possible value?
Am I missing something here?

thank

+45
c # guid
Feb 01 '10 at 15:41
source share
4 answers

The icon is correct. Value types that define their own equality operators automatically get canceled versions that can be canceled. In this situation, apply the null equality operator, which takes two null pointers, will be called, and will always return false.

In C # 2, this caused a warning, but for some reason it stopped issuing a warning for guid-to-null, but continues to issue a warning for int-to-null. I do not know why; I have not had time to investigate.

I apologize for the mistake; I probably messed up one of the warning detection code codes when overwriting null logic in C # 3. Adding expression trees to the language significantly changed the order in which null arithmetic operations were implemented; I made a lot of mistakes moving this code. This is complicated code.

+73
Feb 01 2018-10-01
source share

The comparison is fair because the compiler converts Guid to Nullable<Guid> , and then it makes sense.

There is an error report warning that there is no warning here .

See here here for a more complete explanation of Eric Lippert.

+13
Feb 01 2018-10-01
source share

In fact, there is a case where Guild == null will return true.

However, this is difficult to explain.

In ORM mapping structures (e.g. openAccess), when you have a Guid field that will have a default value of Guid.Empty, of course, it is possible to have a script:

  • You add a new field Guid + property
  • You are updating the old database schema .. in this case, all values ​​will be NULL in the database.
  • If you populate an object that has this null column of type Guild, of course, the WILL object will get the value Guid.Empty HOWEVER, if you use the LINQ query ... in the LINQ query, it looks like Guid is not populated yet, so you need to use == null. This may be a mistake, but it is.

In short (using OpenAccess, but probably not only):

var item = GetItems (). Where (i => i.SomeGuidField == null); will work and you will get items with null guid this after updating the circuit. item.First (). SomeGuidField returns Empty Guid

var item = GetItems (). Where (i => i.SomeGuidField == Guid.Empty); will not work even if after the collection of an element it will be Guid.Empty and will return an empty result.

+2
Mar 26 '13 at 9:27
source share

Of course, this is not only a problem for Guid . The same behavior is observed with any type of struct that is not a predefined type of C #, provided that struct overloads operator == usual way. Other examples within the framework include DateTime and TimeSpan .

This deserves a warning about compilation time, since being technically legal due to a raised statement, this is not useful since it always gives false . Thus, this indicates a programmer error.

As Eric Lippert said in his answer, the compile-time compiler existed along with the Visual C # 2.0 compiler. In versions 3.0 through 5.0, a warning was accidentally omitted (for these "user-defined" struct types, but not for predefined value types such as int , and not for enumeration types).

Since C # 6.0 (based on Roslyn), the compiler again detects this code problem. However, due to backward compatibility (!), A warning is not issued if you do not compile your code with the so-called strict function.

To enable strict mode, when you use the .csproj file (in most cases), unload the project from Visual Studio, edit the file, insert the XML element:

 <Features>strict</Features> 

in each <PropertyGroup> (usually there will be more than one) of the .csproj file. Then you get a warning (it can be β€œadvanced” to an error if you use the Warning warning as an error).

If you cannot edit .csproj , and if you call msbuild.exe from the command line to compile, use the switch:

 /p:Features=strict 

to msbuild.exe .

If you are not using .csproj files because you are compiling directly with csc.exe (C # compiler), use the switch:

 /features:strict 

to csc.exe on the command line.

0
Dec 09 '16 at 21:23
source share



All Articles