34

Is there a performance benefit to one way over the other?

Are there other reasons to choose one over the other?

David W
  • 483
  • 4
  • 11

3 Answers3

51

Is there a performance benefit to one way over the other?

No. They both compile to the exact same IL. The cast is syntactic sugar for the Value property. This code:

int? x = null;
Console.WriteLine(x.Value);
Console.WriteLine((int)x);

compiles to these IL instructions, ignoring nops: (you can test this yourself using ildasm, ILSpy, DotPeek, etc.)

// int? x = null;
ldloca.s 0
initobj valuetype [mscorlib]System.Nullable`1<int32>

// Console.WriteLine(x.Value);
ldloca.s 0
call instance !!0 [mscorlib]System.Nullable`1<int32>::get_Value()
call void [mscorlib]System.Console::WriteLine(int32)

// Console.WriteLine((int)x);
ldloca.s 0
call instance !!0 [mscorlib]System.Nullable`1<int32>::get_Value()
call void [mscorlib]System.Console::WriteLine(int32)

Are there other reasons to choose one over the other?

I prefer to avoid casts when I can, because there's always the potential for them to get out of sync with the actual type. If I change my variable from int? to byte?, then all my casts are wrong -- but if I was using .Value, I'm free to change the variable as necessary. To me, the hard cast doesn't add anything in terms of readability, but it does cost in terms of maintainability.

Joe White
  • 94,807
  • 60
  • 220
  • 330
  • 5
    .Value will also get out of sync if the type is no longer nullable. I prefer casting because then if things change I will know exactly where there could be problems. – Telavian Oct 08 '14 at 17:00
  • 3
    @Telavian If the type is no longer nullable then wouldn't `.Value` also fail to compile? So either way, cast or not you'd have to address some semantic issues. – void.pointer Mar 18 '21 at 20:32
10

Is there a performance benefit to one way over the other?

Performance would be negligible

Are there other reasons to choose one over the other?

Readability?


// most readable
public int GetValue(int? value)
{
    return value.GetValueOrDefault();
}

// less readable
public int GetValue(int? value)
{
    return value ?? default(int);
}

// least readable
public int GetValue(int? value)
{
    return value.HasValue ? value.Value : default(int);
}

//least readable reversed return type/param type
public int? GetValue(int value)
{
    return value == 0 ? null : (int?)value;
}
hunter
  • 62,308
  • 19
  • 113
  • 113
4

(Old question? Who cares. Contemporary problem.)

First, Joe provides a great answer, and given the current state of C#, I guess I agree with him:

... potential for them to get out of sync with the actual type. If I change my variable from int? to byte?, then all my casts are wrong -- but if I was using .Value, I'm free to change the variable as necessary.

The problem is that you always are committing to a type, because if you use .Value then you are committing to Nullable<TAny> and if you're using the cast you're committing to "ICastableTo<TSpecific>"made up name

That said, Joe's advice is still valid, because the compiler will be much better at catching invalid .Value usage than potentially semantically invalid casts that may still compile, and you want the compiler to catch as much stuff as it can when changing types.

Community
  • 1
  • 1
Martin Ba
  • 37,187
  • 33
  • 183
  • 337