Nullable DateTime extension throws 'does not contain a definition' exception
Asked Answered
G

2

13

In the code below:

void Main()
{
    DateTime cleanDate = DateTime.Now.ToCleanDateTime();    
    DateTime? nullableCleanDate = DateTime.Now;
    nullableCleanDate = nullableCleanDate.ToCleanDateTime();

    cleanDate.Dump();
    nullableCleanDate.Dump();
}

public static class Extensions
{
    //public static DateTime ToCleanDateTime(this DateTime dt)
    //{
    //  dt = new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0, 0);
    //  return dt;
    //}

    public static DateTime? ToCleanDateTime(this DateTime? dt)
    {
        if (dt.HasValue)
            dt = new DateTime(dt.Value.Year, dt.Value.Month, dt.Value.Day, 0, 0, 0, 0);
        return dt;
    }
}

This line DateTime cleanDate = DateTime.Now.ToCleanDateTime(); throws following exception.

'System.DateTime' does not contain a definition for 'ToCleanDateTime' and the best extension method overload 'Extensions.ToCleanDateTime(System.DateTime?)' has some invalid arguments

If I comment in extension method for DateTime public static DateTime ToCleanDateTime(this DateTime dt) error is not thrown.

Could anyone enlighten me with:

  1. Why is this error thrown (aside from the obvious)?
  2. Is there a way to combine these two extensions into single method?

I somehow expected public static DateTime? ToCleanDateTime(this DateTime? dt) to handle both DateTime and DateTime?.

Guise answered 28/5, 2015 at 18:33 Comment(1)
As your answer says, DateTime != DateTime? because DateTime? is turned into Nullable<DateTime> by the compiler. Its a completely different type.Elman
C
15

That's not an exception that's thrown, that's a compiler error. The former happens at runtime, the latter at compile time. It's an important difference.

You get this error because the compiler can't find an extension method accepting a DateTime, only one with a DateTime?. Those are entirely different types. Nullable<T> has no inheritance relation whatsoever to T, so you can't make an overload for Nullable<T> accept a T, nor vice versa.

You can combine the methods by letting one call the other:

public static class Extensions
{
    public static DateTime ToCleanDateTime(this DateTime dt)
    {
      return new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0, 0);      
    }

    public static DateTime? ToCleanDateTime(this DateTime? dt)
    {
        if (dt.HasValue)
        {
            return dt.Value.ToCleanDateTime();
        }
        return dt;
    }
}

Or you can just use DateTime.Date, which returns the same as your extension method and preserves the Kind, as opposed to the above code with which Kind will be Unspecified regardless the input's Kind.

Canoness answered 28/5, 2015 at 18:35 Comment(0)
S
4

If dt has datatype DateTime?, you can use dt.value.Month and dt.Value.Year etc to fetch the data

Sirius answered 11/8, 2021 at 6:33 Comment(1)
This does not answer the question.Wifehood

© 2022 - 2024 — McMap. All rights reserved.