19

After reading on stackoverflow that in the case of checking the format of a DateTime you should use DateTime.TryParse. After trying some regex expressions they seem to get long and nasty looking to cover lots of the formatting.

But TryParse requires an "out" parameter and since I just want to do a validation format check I don't need the actual result.

So I am left with a variable that holds the "out" result and am to do nothing with it. Is there a way so I don't have to do a out parameter?

So I get rid of this warning and stop having a variable just flying around.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
chobo2
  • 83,322
  • 195
  • 530
  • 832

6 Answers6

36

With C#7.0 (since August 2016) you can use the out var construct, and then just ignore the new var in subsequent code.

bool success = DateTime.TryParse(value, out var result);

If you truly do not care about the value of the result, use discards:

bool success = DateTime.TryParse(value, out _);
jeubank12
  • 891
  • 9
  • 17
  • 2
    This should be the highest voted answer. 'result' goes out of scope immediately. – fafrd Nov 30 '17 at 20:34
  • 1
    This will actually keep 'result' for code within the same scope. Within a method you can check the success and have the result value (or default(DateTime)). Also this notation was not supported prior to C#7 – jeubank12 Dec 01 '17 at 22:19
22

Nope. I'd wrap it in a method somewhere to keep the noise out of the main flow:

  bool IsValidDate(string value)
  {
     DateTime result;
     return DateTime.TryParse(value, out result); //result is stored, but you only care about the return value of TryParse()
  }
Cemafor
  • 1,633
  • 12
  • 27
Kim Gräsman
  • 7,438
  • 1
  • 28
  • 41
  • 6
    I'd consider expanding the elipsis to the actual params in your answer – MPritchard Sep 12 '09 at 06:37
  • @Martin -- thanks, yes, I considered that, too, but since we don't know what format string chobo2 will be using, I figured he knew the details better than me. – Kim Gräsman Sep 12 '09 at 06:48
  • I don't really set a format provider. I have in my webconfig set to US culture so all dates should be in U.S date format. – chobo2 Sep 12 '09 at 07:12
  • Well if I have many out parameters that I am using then I will do this but for one I am not going to wrap it. I was just hoping there was some way to use null or something. This is good to know in the future though. – chobo2 Sep 12 '09 at 07:16
7

I'm not suggesting you actually do this, but you could use a single helper class to make this easy for all out parameters:

public static class OutHelper<T>
{
    [ThreadStatic]
    public static T Ignored;
}

Then you can call:

if (DateTime.TryParse(text, out OutHelper<DateTime>.Ignored))

It's horrible, uses a public mutable field, and if your application is also executing with some malicious code, it gives that code access to the last value you've parsed... but it should work :)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    @Mehrdad: In what way is it not thread-safe? The idea is that you never read from the value, so who cares if it's written to multiple times? It *would* potentially cause a failure if the method you called first wrote to the out parameter and then read it afterwards... but that sounds like a bad idea anyway. Obviously it's still a horrible idea in general though :) – Jon Skeet Sep 12 '09 at 10:27
  • 1
    @Jon: I meant exactly the situation where the callee uses the `out` parameter as a temporary storage which will also contain the return value when it finishes. While this is a bad idea for the callee to assume it won't change, it's a natural expectation. Using a global variable for that purpose seriously breaks this assumption. Anyway, as you mentioned it's mostly a "trick" kind of thing and should be avoided in practice. – Mehrdad Afshari Sep 12 '09 at 12:05
  • To be honest, using *any* variable which is shared between threads would have this problem. It could be an instance variable of some object, for example. Something to watch out for when using out variables, I guess... – Jon Skeet Sep 12 '09 at 12:19
  • 2
    @Mehrdad: I've just thought, there's a simple fix to it... editing :) – Jon Skeet Sep 12 '09 at 12:20
4

No. You can't get rid of the variable but you shouldn't get a compiler warning either.

Passing a variable as out is "using" the variable. The compiler will not issue a warning because of that.

Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
4

If you are using .NET 3 and above, you could always create an Extension method?

public static bool IsValidDate(this string value)
{
  DateTime date = DateTime.Null;
  return DateTime.TryParse(value, out date);
}

[Edited to rename the method name to a more appropriate one]

Pete OHanlon
  • 9,086
  • 2
  • 29
  • 28
  • 2
    You don't need to initialize a variable before passing it as an `out` argument. Just declaring it would suffice. – Mehrdad Afshari Sep 12 '09 at 06:42
  • True. It's just a defensive habit I have. – Pete OHanlon Sep 12 '09 at 06:46
  • 10
    Actually, in C#, this "defensive" habit is unnecessary at best and actually bad at worse since the compiler itself will enforce definite initialization of the variable and won't compile if it's used before it's initialized. If you initialize a variable when it's not really needed, and then forget to pass it to the method as an `out` argument, "defensiveness" will cause make the error silently go away. – Mehrdad Afshari Sep 12 '09 at 06:53
1

TryParse is a better option. Its just a variable that is wasted. Other options include using the Convert.ToDateTime() within a try-catch block. But again that would not be efficient because try-catch blocks are meant to be heavy. The next option is regex. This is a better solution. I guess this gives you the result instantly than compared to the others.

You can very well wrap the method like Kim Gräsman said...

frogatto
  • 28,539
  • 11
  • 83
  • 129
deostroll
  • 11,661
  • 21
  • 90
  • 161
  • Ya in the end of the day it really is no big deal that I have on variable flying around but I really thing you should be able to use null or something. Or they should have just a parser that just checks and does not return anything. – chobo2 Sep 12 '09 at 07:15