1

I have a problem which may be a bug in code contracts or I'm just missing something.

I have a class with a nullable DateTime property DateValue which gets set by the constructor. The class's == overload states that 2 objects are equal if first.DateValue == second.DateValue. Strangely, this comparison causes code contract warning:

The Boolean condition first.DateValue.HasValue always evaluates to a constant value. If it (or its negation) appear in the source code, you may have some dead code or redundant check

// relevant code only. full code posted later
public class ClassWithDate
{
    public DateTime? DateValue { get; private set; }

    public ClassWithDate(DateTime? dateValue)
    {
        DateValue = dateValue;
    }

    public static bool operator ==(ClassWithDate first, ClassWithDate second)
    {
        // ...

        // !! CODE CONTRACT WARNING HERE !!
        return (first.DateValue == second.DateValue);
    }

    // ...
}

I don't understand why the rewriter would think that DateValue.HasValue is always a constant value, nor what it has to do with DateTime equality.

Am I missing something with code contracts? Or with the equality overloads? Could this be a bug in code contracts?

Full code below.

public class ClassWithDate
{
    public DateTime? DateValue { get; private set; }

    public ClassWithDate(DateTime? dateValue)
    {
        DateValue = dateValue;
    }

    public override bool Equals(object obj)
    {
        return ((obj as ClassWithDate) != null) && (this == (ClassWithDate)obj);
    }

    public static bool operator ==(ClassWithDate first, ClassWithDate second)
    {
        if (object.ReferenceEquals(first, second)) return true;
        if (((object)first == null) || ((object)second == null)) return false;

        // compare dates
        return (first.DateValue == second.DateValue);
    }

    public static bool operator !=(ClassWithDate first, ClassWithDate second)
    {
        return !(first == second);
    }

    public override int GetHashCode()
    {
        return (DateValue == null ? 0 : DateValue.GetHashCode());
    }
}
Brendan Green
  • 11,676
  • 5
  • 44
  • 76
Keith
  • 20,636
  • 11
  • 84
  • 125
  • DateTime is a structure not an object -- it is a Value type. – Hogan Oct 12 '15 at 04:08
  • Huh. Honestly this is a puzzle even for me. I'll be interested to see the solution. – MutantOctopus Oct 12 '15 at 04:35
  • If it is a value type has value will always be true. I didn't look that hard in the reference source for it but a nullable datetime does not make sense. Probably just set the value to zero... It is still a legal value for datetime, so the warning is valid. – Hogan Oct 12 '15 at 11:27
  • Here you go: http://stackoverflow.com/questions/2194617/why-does-nullablet-hasvalue-property-not-throw-nullreferenceexception-on-nulls – Hogan Oct 12 '15 at 16:01
  • @Hogan HasValue can be false for Nullable. This simple example proves that: `DateTime? x = null; Console.WriteLine( x.HasValue ); /* output is 'false' */` Also the link you provided is for a much different case than mine. – Keith Oct 12 '15 at 23:43
  • I guess code contracts is looking at this http://referencesource.microsoft.com/#mscorlib/system/nullable.cs,ffebe438fd9cbf0e – Hogan Oct 13 '15 at 00:51

1 Answers1

1

From my experience this is a bug in Code Contracts. I have encountered it in other situations. Take a look at this question (and answers), which is similar in nature to your issue: CodeContracts: Boolean condition evaluates to a constant value, why?

Ɖiamond ǤeezeƦ
  • 3,223
  • 3
  • 28
  • 40
  • To work around this bug, I decided to ignore the error using the `ContractVerification` attribute per this answer: http://stackoverflow.com/a/3662612/65775 – Keith Oct 19 '15 at 21:27