1

I just figured out, that it is possible to use the is-keyword in C# for a null check on nullable stucts. I think it looks quite clean and is good to understand, but is it also performant? Does the interpreter has to double cast it or is it okay that way?

    static void Main(string[] args)
    {
        DateTime? test = null;

        PrintDT(test);//wont print
        test = DateTime.Now;
        PrintDT(test);//will print
    }
    private static void PrintDT(DateTime? dt)
    {
        if (dt is DateTime a)
            Console.WriteLine(a);
    }
Max R.
  • 811
  • 1
  • 13
  • 31
  • It would be OK, if you cast anything unknown, like an object to DateTime. But if the origin type is already DateTime?, than better use dt.HasValue, and if true, dt.Value. This involves no casting or boxing, it's just accessing it. – Holger Jan 08 '20 at 15:35
  • @Holger disagree completely. The compiler knows how to deal with nullable types as part of the language and the (typical) programmer doesn't need to dive into the implementation details of how the nullables are implemented. – Jesse C. Slicer Jan 08 '20 at 16:51
  • @JesseC.Slicer, I have no idea what you talking about. The Type DateTime? has only two public properties, HasValue and Value. That is not "implementation details", that's the basics. You say something like, then using a List, you don't need to know about List.Add. That's the recommended way to convert a nullable value type, to its non-nullable type. And a programmer using nullables needs to know that necessarily, he couldn't use this data-type otherwise. – Holger Jan 08 '20 at 17:24
  • @Holger also incorrect. `dt != null` is equivalent to `dt.HasValue` and `(DateTime)dt` is equivalent to `dt.Value`. You simply don't need to know those methods. – Jesse C. Slicer Jan 08 '20 at 17:28
  • @JesseC.Slicer Yes, there are casting rules that are applied implicitly. But this discussion is strongly opinion based. I prefer explicit over implicit, and Intellisense suggests those properties by itself, it's not hard to learn. It's OK, there is more than one method to do things, but there is never a ranking of methods. And for performance, you need to know some details. The topic here was the is-operator. And you agree, we should not use it, cause it's also not part of your answer. – Holger Jan 08 '20 at 17:41
  • @Holger I did not agree on not using it. I think it's an excellent representation. – Jesse C. Slicer Jan 08 '20 at 18:20
  • Possible duplicate of https://stackoverflow.com/questions/58505313/proper-null-check-on-service-result-in-c-sharp-net ? Not sure, I'm asking. –  Jan 08 '20 at 19:12

1 Answers1

6

Any tool that compiles/decompiles back to C# will give the equivalent method (release mode compile):

private static void PrintDT(DateTime? dt)
{
    if (dt.HasValue)
    {
        DateTime valueOrDefault = dt.GetValueOrDefault();
        Console.WriteLine(valueOrDefault);
    }
}

or (debug mode compile)

private static void PrintDT(DateTime? dt)
{
  DateTime valueOrDefault;
  int num;
  if (dt.HasValue)
  {
    valueOrDefault = dt.GetValueOrDefault();
    num = 1;
  }
  else
    num = 0;
  if (num == 0)
    return;
  Console.WriteLine((object) valueOrDefault);
}

So the compiler is using the nullable type syntactic sugar up front to create an optimized scenario behind the scenes.

Jesse C. Slicer
  • 19,901
  • 3
  • 68
  • 87
  • but wouldn't `if (dt.HasValue) Console.WriteLine(dt.Value);` be better as we don't have to introduce a new variable? Or does the compiler does a clean up anyway so it will be the same in the end? – Max R. Jan 08 '20 at 15:38
  • 1
    I'm just showing what a decompiler comes up with. I would agree with your assertion for this case. My guess is the compiler cannot make certain assumptions that we can looking at the code. I'm certain someone like Eric Lippert or Jon Skeet could explain precisely why it does what it does, but rest assured it falls under the "don't screw something up" header. – Jesse C. Slicer Jan 08 '20 at 16:56
  • 1
    @MaxR. variables are just names, not actual values. Besides, even in .NET Old, [GetValueOrDefault](https://referencesource.microsoft.com/#mscorlib/system/nullable.cs,55) simply returns the value – Panagiotis Kanavos Jan 08 '20 at 19:14
  • @PanagiotisKanavos So if I understand you correctly, in the end performance will not be affected in either ways? – Max R. Jan 08 '20 at 23:02
  • @MaxR. if you check the link you'll see that `.Value` performs a check before the call to `return value` and throws if that fails so `GetValueOrDefault` is faster by .... 1 CPU operation in the good case or pays the cost for throwing if empty – Panagiotis Kanavos Jan 09 '20 at 07:58
  • @PanagiotisKanavos Yes, i understood that, my concern was on your first sentence. "variables are just names, not actual values", so it is safe to assume that it wont affect performance at all? – Max R. Jan 09 '20 at 10:40