Nullable Types in C#

April 25th, 2006

One of the “late-breaking features” of C# 2.0 was nullable types. They are supposed to make object-relational mapping easier, being effectively nullable primitives which behave more closely like the types in SQL. However I have just spent an hour debugging a problem which demonstrates very clearly how language features such as this simply make life more difficult for developers.

In .NET, as in most object oriented languages, there is a distinction between primitive types and objects. In C#, as in C++, it is possible to define your own primitives using the struct keyword. C# structs cannot be inherited from, cannot have null assigned to them, and have their memory allocated from the stack instead of the heap.

The fact that structs are not nullable is a frequent irritation when coding in C#. For example, the .NET DateTime type is defined as a struct, and so when designing a form which has an optional date field, much messing around results. Your options are basically to create an object which wraps the DateTime struct, or to make DateTime.MinValue behave like null. Even though the latter is clearly evil and dirty, for some reason we have adopted it in our code.

With the advent of generics in C# 2.0, a solution was devised for this problem. First of all, the .NET framework provides a struct called Nullable<T>, which behaves like a wrapper for primitives. Then they added some syntactical sugar such that when you append ? to a primitive declaration, it compiles into an object of type Nullable<primitive>. So for example decimal? needlesInMyEye becomes Nullable<decimal> needlesInMyEye.

However this becomes a pain in the ass exactly where you most want it – when doing object relational mapping. So in my current project we’re binding a field in our form to a property of one of our domain objects. The property in question is mapped to a NOT NULL field in the relevant table, and so in the class definition it is defined as decimal?. Weirdly though, the binding fails. When you enter the string “12.5″ in the form field, the property gets assigned “null”. If you remove the ?, the binding works and the property gets assigned the value 12.5.

Once you know how the syntactical sugar works and hence what is happening under the hood, it is obvious why this occurs. The form field binding knows how to cast a string to a decimal, but not how to cast a string to an object of type Nullable<decimal>, and so assigns null to it instead. So we’ve introduced a temporary hack to by providing a wrapper for the property which takes type string and does the parsing explicitly. Great.

More generally, it is tempting for developers to mix nullable and non-nullable types in the domain, believing they are basically the same type of thing when in fact they are fundamentally different. You then end up in a situation where you don’t know if you’re dealing with a generic struct or a primitive. Since these types are not interchangeable, you are just going to end up with a series of hacks throughout the codebase like the one described in the paragraph above.

I think the root problem is having a distinction between primitives and objects in the first place. In languages like Smalltalk and Ruby there is no such distinction – everything is an object. Clearly the fact that these languages are neither strongly nor statically typed removes the problem of casting and makes it easier to avoid primitives. But I would love to have people give me some good reasons why C# and Java require primitives (over and above arguments based on speed and efficiency).

Meanwhile the advice is clear: don’t mix and match nullable types and primitives; they won’t autobox and they aren’t interchangeable. To avoid confusion, prefer objects to nullable types – in almost all cases you’ll have behaviour you want to give them, in which case you’ll want objects in any case. In particular, having static methods that operate on nullable types is a clear warning sign that what you actually want is an object.

Update: binding to nullable types in WinForms

Originally in this update I provided a complicated solution to the problem mentioned above that binding to nullable types didn’t appear to work. It turns out that it in fact does work, provided you explicitly set the DataSourceUpdateMode to DataSourceUpdateMode.OnPropertyChanged (new in .NET 2.0) when doing the binding. Thanks to Edbert for the tip (see comment below).

  • Edbert

    Binding to nullables work in WinForms.
    I had the same problem before where the nullable won’t be updated. However, passing extra arguments seem to fix it for some reason (haven’t checked into the details yet), e.g.
    bind = new Binding(“ValueObject”, bindingSource, “FeeAmount”, true, DataSourceUpdateMode.OnPropertyChanged);

  • jez

    Hi Edbert. Thanks for the tip – quite right, adding DataSourceUpdateMode.OnPropertyChanged makes setting properties on nullable types work. So for example when you bind a property of type int? to a text field, setting the text field to an empty string makes the property null.

    The DataSourceUpdateMode enum is new in .NET 2.0, and the default value if you don’t explicitly specify it is DataSourceUpdateMode.OnValidation. From the documentation:

    OnPropertyChanged: Data source is updated whenever the value of the control property changes.
    OnValidation: Data source is updated when the control property is validated. After validation, the value in the control property will also be re-formatted.
    Never: Data source is never updated and values entered into the control are not parsed, validated or re-formatted.

  • Sean Smith

    Wow this took me a long time to figure out. I had a long complicated method of working around it also for a DateTime?, but as soon as I read this is just popped. I knew that there had to be a way to make nullable types work with the DateTimePicker and ShowCheckBox = true; Thanks Edbert!

  • http://www.drunkencoders.com jason

    Thanks, we were scratching our heads over this for a bit. Just in case no one else wants to waste the 5 minutes we did, the DataSourceUpdateMode can be set to OnPropertyChanged from the gui under the advanced data binding tab on the control properties

  • Dirk Huber

    Maybe I missunderstood something wrong, but what do I have to do to edit a Nullable Property with a DateTimePicker Control?

    When I understand it right I only have to use DataSourceUpdateMode.OnPropertyChanged and Set ShowCheckBox to true?

  • Chris Woodcock

    I was having problems just now with binding a ComboBox “SelectedValue” to a property which was Nullable and tried the suggestions above but I found that the DataSourceUpdateMode didn’t make any difference it was the formattingEnabled parameter which makes this work – it must be “true” for some reason!

    bind = new Binding(”ValueObject”, bindingSource, “FeeAmount”, true, DataSourceUpdateMode.OnPropertyChanged);

  • Mario

    Edbert, you rule tonight man. Thanks, I think is just one more bug from Redmond.

  • Pingback: Binding to Nullable(Of T) properties | keyongtech