Search code examples
c#visual-studio.net-corecompiler-warnings

Why is there no compiler warning for comparing DateTime to null?


Visual Studio shows compiler warning CS04721 under (int)5 == null which reads

The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?'

bool x = (int)5 == null;

However, there is no warning if a DateTime object is used.

bool y = DateTime.UtcNow == null;

Since DateTime is not Nullable<DateTime>, it can never be null. What's the reason a similar warning is not shown for the second statement?


Solution

  • The code

    bool x = (int)5 == null;
    

    produces the warning number CS0472 which has existed since the first version of C#.

    The code

    bool y = DateTime.UtcNow == null;
    

    produces the warning number CS8073. According to its help page, the warning CS8073 is part of the "warning wave 5" and was only introduced with C# version 9.

    So you will see the warning when using C# 9 or newer and you won't see it when using older versions.

    Whether you see the warning will also be influenced by the " AnalysisLevel" you configure in the project options of your project. To see warning CS8073, you should have enabled warning level 5 or higher.

    Warning CS8073 specifically applies to struct types while the older warning deals with built-in primitive value types.


    There is a blog post by Microsoft that announces the introduction of new warnings. According to the blog post, warning CS8073 was introduced because it deals with a "common coding mistake".


    Why the warning hasn't been implemented earlier can only be guessed. My guess is the following:

    The comparison operator from the first example with the type int is built into the language, while the equality operator in the second example is an operator overload in the class DateTime that is implemented as C# code in the .net Framework source code.

    So, in order to generate the warning in the second case, the Compiler has to look at the actual implementation of the struct type and its available operator overloads.

    There could in fact be an overload that allows using the equality operator with a struct type and a different reference type in which case the warning would not be justified because the comparison with null could return true.

    Example of a program where the comparison of a struct type with null will return true (Nullable option is disabled):

    internal class Program
    {
        public struct X
        {
            public static bool operator ==(X s1, object s2) => s1.Equals(s2);
            public static bool operator !=(X s1, object s2) => s1.Equals(s2);
            public override bool Equals(object other) => true;
            public override int GetHashCode() => 0;
        }
    
        static void Main()
        {
            X x = new X();
            bool b = x == null;
            Console.WriteLine(b);
        }
    }