tags:

views:

60

answers:

2

I'm new to nullable types. I like them for adding a value that can mean "no set", but I don't like having to cast them back later on, or having to tack on the .Value.

Here's specifically my scenario in context of a wrapper class that implements one of my repository types:

public DateTime TimeCreated
    {
        get { return inner.TimeCreated.IsSet() ? inner.TimeCreated.GetValue() : DateTime.MaxValue; }
    }

I'd like to change to using DateTime? but as I understand it, then when I access the property I have to use either (DateTime)TimeCreated or TimeCreated.Value and, for me, it kind of defeats the purpose of wrapping the type in the first place having to add verbosity to any code that accesses it.

Question: is there an easy workaround for this? Or am I missing some point, as I feel may be the case?

+4  A: 

Casting from a Nullable<T> to T is a narrowing conversion, as the new type cannot represent the value 'null'. Any time you have a narrowing conversion, it's good to make it explicit, to help remind the developer that it might fail.


On a side note, you don't need the cast if you use the null-coalescing operator, since this removes the opportunity for failure:

int? someValue = X;
int realValue = someValue ?? int.MaxValue;
Dan Bryant
now I understand the rationale, thanks. It would be nice if I could work around it if I, say, was willing to risk an exception being thrown
Gabriel
@Gabriel, the design philosophy of C# tends to err on the side of caution when it comes to auto-magical conversions. There are other languages which are much looser when it comes to conversions and comparisons. This can be convenient (more concise code), but it can also lead to some really befuddling bugs. I'm sure there are Javascript coders out there who can relate.
Dan Bryant
@Dan, I just had a thought - if the ?? operator relaxes the requirement, it seems like a small leap to the compiler allowing implicit casting if the code is down stream of static guard expression like if(someValue!=null)
Gabriel
@Gabriel, You can always ask @Eric Lippert to add it to the list. :) Of course you then have to deal with checking whether the value could have been modified after the static guard expression, which means it either has to be an umodified local or a readonly field, but then you also have to be careful that the unmodified local wasn't previously captured in a closure, which could allow it to change after the check. As they say, the devil is in the details.
Dan Bryant
another good point, thanks for keeping me on my toes
Gabriel
@Gabriel, firstly ?? relaxes the requirement and provides a behaviour for when it isn't met. There is a world of difference between `x ?? int.MinValue` and `x ?? int.MaxValue` after all. Secondly, your guard expression could be immediately followed by a cast or call to `.Value`, in which case there's no need to complicate the language in a difficult to determine way (if I know the type and I have to scroll to know if a call on it will compile, I'm not happy), when you can just call on the result of that initial cast.
Jon Hanna
+1  A: 

This doesn't really directly answer your question, but if this type of thing is common and important to you, it might be worthwhile to consider other options. For example, F# has a completely different mechanism for dealing such situations and "null" rather uncommon.

Dan