7 Replies - 277 Views - Last Post: 20 November 2019 - 03:22 PM Rate Topic: -----

#1 andrewsw   User is online

  • never lube your breaks
  • member icon

Reputation: 6823
  • View blog
  • Posts: 28,271
  • Joined: 12-December 12

out DateTime?

Posted 19 November 2019 - 01:24 AM

This is most likely trivial, but I have a head-cold :(

We have a terrible set-up to retrieve database values, which are parsed as XML - don't ask me why they did this?!

Anyway, I want to retrieve a DateTime value which could be null, and am attempting with this code:

        DateTime? dateCompleted = null;

        DateTime.TryParse(xe2.Element("DateCompleted").Value, out dateCompleted);

The error indicated on the out value is "cannot convert from out DateTime? to out DateTime".

So the out value should be DateTime (not nullable). Switching to

        DateTime dateCompleted;

        DateTime.TryParse(xe2.Element("DateCompleted").Value, out dateCompleted);

would work but then I cannot assign dataCompleted the value of null; I would have to introduce a second variable.

Is there a simple, elegant, way to resolve this?

I suppose I could use Parse instead and trap an error, but that doesn't seem elegant.

Is This A Good Question/Topic? 0
  • +

Replies To: out DateTime?

#2 andrewsw   User is online

  • never lube your breaks
  • member icon

Reputation: 6823
  • View blog
  • Posts: 28,271
  • Joined: 12-December 12

Re: out DateTime?

Posted 19 November 2019 - 01:32 AM

Found this SO link,

DateTime? d = DateTime.TryParse("some date text", out DateTime dt) ? dt : null;


Ugh, two variables... Although, I believe this is C# 6 anyway.
Was This Post Helpful? 0
  • +
  • -

#3 andrewsw   User is online

  • never lube your breaks
  • member icon

Reputation: 6823
  • View blog
  • Posts: 28,271
  • Joined: 12-December 12

Re: out DateTime?

Posted 19 November 2019 - 01:38 AM

Ah well, looks like I'll go with this nonsense:

    DateTime dateCompletedTest;
    DateTime? dateCompleted = null;

    if (DateTime.TryParse(xe2.Element("DateCompleted").Value, out dateCompletedTest))
        dateCompleted = dateCompletedTest;

Was This Post Helpful? 0
  • +
  • -

#4 ndc85430   User is offline

  • I think you'll find it's "Dr"
  • member icon

Reputation: 981
  • View blog
  • Posts: 3,870
  • Joined: 13-June 14

Re: out DateTime?

Posted 19 November 2019 - 02:40 AM

I'm not a C# programmer (obviously!), but it seems odd that it works like that. Is there really no version of TryParse that returns the value instead of mutating something?!
Was This Post Helpful? 0
  • +
  • -

#5 andrewsw   User is online

  • never lube your breaks
  • member icon

Reputation: 6823
  • View blog
  • Posts: 28,271
  • Joined: 12-December 12

Re: out DateTime?

Posted 19 November 2019 - 03:23 AM

The advantage of TryParse against Parse or ParseExact is that it doesn't raise an exception, but, as shown, it cannot resolve DateTime <-> DateTime? (nullable).

I still need the second variable, or I could use Parse and trap the specific ArgumentNullException, which is equally inelegant.
Was This Post Helpful? 0
  • +
  • -

#6 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7132
  • View blog
  • Posts: 24,221
  • Joined: 05-May 12

Re: out DateTime?

Posted 19 November 2019 - 05:03 AM

View Postandrewsw, on 19 November 2019 - 03:38 AM, said:

Ah well, looks like I'll go with this nonsense:

    DateTime dateCompletedTest;
    DateTime? dateCompleted = null;

    if (DateTime.TryParse(xe2.Element("DateCompleted").Value, out dateCompletedTest))
        dateCompleted = dateCompletedTest;


Which is the same as C# 6's:
DateTime? dateCompleted = null;

if (DateTime.TryParse(xe2.Element("DateCompleted").Value, out DateTime dateCompletedTest))
    dateCompleted = dateCompletedTest;



which will bring you right back around to:
DateTime? dateCompleted = DateTime.TryParse(xe2.Element("DateCompleted").Value, out DateTime dateCompletedTest)
    ? dateCompletedTest
    : null;


Was This Post Helpful? 1
  • +
  • -

#7 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7500
  • View blog
  • Posts: 15,541
  • Joined: 16-October 07

Re: out DateTime?

Posted 20 November 2019 - 09:28 AM

To me, this is where an extension method really improves your life.

First some play code.
// I don't usually use the linky one, but ok.
// var doc = new XmlDocument(); doc.Load("Books.xml"); var books = doc.SelectNodes("/catalog/book");
var doc = Xdocument.Load("Books.xml");
foreach (var book in doc.Root.Elements("book")) {
    Debug.WriteLine(book.Element("title").Value);
    Debug.WriteLine(book.Element("publish_date").Value);
    // Error	CS0173	Type of conditional expression cannot be determined because there is no implicit conversion between 'DateTime' and '<null>'
    // DateTime? pubDate = DateTime.TryParse(book.Element("publish_date").Value, out DateTime pubDateTest) ? pubDateTest : null;
    // I've run into this before.  I don't know Skydiver's trick for not having that barf, so...
    DateTime? pubDate = null;
    if (DateTime.TryParse(book.Element("publish_date").Value, out DateTime dtOut)) { pubDate = dtOut; }
    Debug.WriteLine(pubDate);
    Debug.WriteLine("---");
}



I grabbed some public XML here. I also blanked out a some to test the null functionality.

Now, with an extension method, you can put this mess in a safe, sensible, place.
Something like this:
public static class ExXDocument {
    public static DateTime? ToDateTimeNullable(this XElement ele) {
        if (DateTime.TryParse(ele.Value, out DateTime dtOut)) { return dtOut; }
        return null;
    }
}



Making the conversion thing a one liner:
Debug.WriteLine(book.Element("title").Value);
Debug.WriteLine(book.Element("publish_date").ToDateTimeNullable());



For even more generic solutions, I use something like:
public static T? GetValueOrNullStruct<T>(this XElement ele) where T : struct {
    if (ele.Value != null) {
        try { return (T)Convert.ChangeType(ele.Value, typeof(T)); } catch { }
    }
    return null;
}
public static T GetValueOrNull<T>(this XElement ele) where T : class {
    if (ele.Value != null) {
        try { return (T)Convert.ChangeType(ele.Value, typeof(T)); } catch { }
    }
    return null;
}



You can also do similar methods to allows for those nasty times with an element name is optional...

As an aside, if there's one piece of code I use more than anything else I've ever written, it's this:
public static T GetValueOr<T>(this IDataRecord rec, T defaultValue, int index) {
    if (!rec.IsDBNull(index)) {
        var value = rec.GetValue(index);
        if (value != null) {
            try {
                return (T)Convert.ChangeType(value.ToString(), typeof(T));
            } catch {
            }
        }
    }
    return defaultValue;
}



The defaultValue gives the type reference, so database pulls tend to look like Id = rec.GetValueOr(0,0), Name = rec.GetValueOr("",1).
Was This Post Helpful? 2
  • +
  • -

#8 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7132
  • View blog
  • Posts: 24,221
  • Joined: 05-May 12

Re: out DateTime?

Posted 20 November 2019 - 03:22 PM

View Postbaavgai, on 20 November 2019 - 11:28 AM, said:

I've run into this before. I don't know Skydiver's trick for not having that barf, so...

No trick. My code barfs too without the casts for the simple types. For custom types, it's possible to declare the conversion operators.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1