Nullable Types

AID: 2875
  • Status: Published

2140 points

  • Byivostoykov
  • TypeReview
  • Posted on2010-04-15 at 06:24:49
Awards
  • Community Pick
C# And Nullable Types

Since 2.0 C# has Nullable(T) Generic Structure. The idea behind is to allow value type objects to have null values just like reference types have. This concerns scenarios where not all data sources have values (like a database column for instance) and assigning a value will change the result.
Nullable type is applicable to primitive (known as value) types where data is stored in the stack and .NET Framework implicitly initializes them to their default values, even though the developer did not do that. Applying Nullable type to primitive types helps going round discomfort of looking for equivalent decisions like creating:

  • A boxed value type. This is not strongly-typed at compile-time, and involves doing a heap allocation for every type.
  • A class wrapper for the value type. This is strongly-typed, but still involves a heap allocation, and the you have to write the wrapper.
  • A struct wrapper that supports the concept of nullability. This is a good solution, but you have to write it yourself.


Nullable types can be declared in two ways:
System.Nullable<T> variable
T? variable
                                    
1:
2:

Select allOpen in new window


T is the underlying type of the variable. It can be a struct but cannot be reference type.

Any value type may be used as the basis for a nullable type. For example:

int? i = 10;
double? d1 = 3.14;
bool? flag = null;
char? letter = 'a';
int?[] arr = new int?[10];
                                    
1:
2:
3:
4:
5:

Select allOpen in new window


Each instance of the above inherits two public read-only properties from Nullable type:
  • HasValue – bool type stating that variable contains a value
  • Value – variable underlying type value meaningful for the type (excluding null). Attempt to get the Value which has no value assigned (HasValue is false) will raise InvalidOperationException.

Testing for meaningful value can be done in two ways
int? x=null;
if(x.HasValue) {...} or
if(x!=null) {…}
                                    
1:
2:
3:

Select allOpen in new window



Some notes about bool value type

When a bool variable is defined as nullable (i.e. bool? a) it can contains tree values: true, false and null. This make it unusable in if, for and while conditional constructions. The following will cause and error:

bool? x = null;
if(x) // will raise error
                                    
1:
2:

Select allOpen in new window


This is because in the case of a null value it is not clear what it means in this context – true or false. To avoid this, check HasValue first and then if it is true, cast to bool. Be aware that if cast is made when value is null an InvalidOperationException will be thrown.

Nullable Type Identification

Using GetType method or the is operator to obtain type information from Nullable variables at runtime will return underlying type not the Nullable type itself. This happens because GetType on a Nullable type will fire boxing to Object.
int? i = 10;
Console.WriteLine(i.GetType().FullName); //"System.Int32"
                                    
1:
2:

Select allOpen in new window


is operator operates on Nullable’s underlying  types and cannot be used to determine whether a variable is Nullable type.
int? i = 10;
Console.WriteLine(i is int); //"True"
                                    
1:
2:

Select allOpen in new window


Boxing

Nullable types can be boxed only if their value is non-null. When value is not null boxing is on the value type itself, not on System.Nullable(T) that wraps the value type.

Boxed nullable types can be tested for null:

bool? b = null;
object bB = b;
if (b == null)  {   /* True. */ }
if (bB == null) { /* Also true. */ }
                                    
1:
2:
3:
4:

Select allOpen in new window


Boxed nullable types has full functionality of the underlying type:

double? d = 44.4;
object iBoxed = d;
// Access IConvertible interface implemented by double.
IConvertible ic = (IConvertible)iBoxed;
int i = ic.ToInt32(null);
string str = ic.ToString();
                                    
1:
2:
3:
4:
5:
6:

Select allOpen in new window


Using Nullable type is very convenient in number of cases and reduce code writing. More info on the topic is available here
http://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx
Asked On
2010-04-15 at 06:24:49ID2875
Tags
Topic

C# Programming Language

Views
1087

Comments

Expert Comment

by: kaufmed on 2010-05-15 at 10:32:19ID: 14553

You might want to make a note about what "boxing" is. I have a feeling that people who do not know about Nullable may also not know what the concept of "boxing" is  :)

Author Comment

by: ivostoykov on 2010-05-16 at 02:07:12ID: 14601

In brief:
(un)boxing = conversion.
  • value -> reference type = boxing (wraps value in a Object)

  • reference -> value type = unboxing (extracts value from a Object)


Here's what Microsoft says about boxing 8-)

Add your Comment

Please Sign up or Log in to comment on this article.

Join Experts Exchange Today

Gain Access to all our Tech Resources

Get personalized answers

Ask unlimited questions

Access Proven Solutions

Search 3.2 million solutions

Read In-Depth How-To Guides

1000+ articles, demos, & tips

Watch Step by Step Tutorials

Learn direct from top tech pros

And Much More!

Your complete tech resource

See Plans and Pricing

30-day free trial. Register in 60 seconds.

Loading Advertisement...

Top C# Experts

  1. kaufmed

    566,376

    Sage

    500 points yesterday

    Profile
    Rank: Genius
  2. BuggyCoder

    240,764

    Guru

    10 points yesterday

    Profile
    Rank: Sage
  3. navneethegde

    158,560

    Guru

    0 points yesterday

    Profile
    Rank: Wizard
  4. CodeCruiser

    140,708

    Master

    2,000 points yesterday

    Profile
    Rank: Genius
  5. TheLearnedOne

    137,350

    Master

    2,800 points yesterday

    Profile
    Rank: Savant
  6. wdosanjos

    124,511

    Master

    3,500 points yesterday

    Profile
    Rank: Genius
  7. AndyAinscow

    107,357

    Master

    0 points yesterday

    Profile
    Rank: Genius
  8. Dhaest

    98,335

    Master

    0 points yesterday

    Profile
    Rank: Genius
  9. Idle_Mind

    91,914

    Master

    0 points yesterday

    Profile
    Rank: Savant
  10. tommyBoy

    90,068

    Master

    0 points yesterday

    Profile
    Rank: Genius
  11. nishantcomp2512

    89,000

    Master

    0 points yesterday

    Profile
    Rank: Wizard
  12. MlandaT

    86,553

    Master

    0 points yesterday

    Profile
    Rank: Genius
  13. Chinmay_Patel

    80,818

    Master

    0 points yesterday

    Profile
    Rank: Genius
  14. ddayx10

    66,538

    Master

    0 points yesterday

    Profile
    Rank: Sage
  15. anarki_jimbel

    66,132

    Master

    2,000 points yesterday

    Profile
    Rank: Genius
  16. ambience

    63,764

    Master

    0 points yesterday

    Profile
    Rank: Sage
  17. ukerandi

    62,593

    Master

    1,000 points yesterday

    Profile
    Rank: Guru
  18. apeter

    60,772

    Master

    0 points yesterday

    Profile
    Rank: Sage
  19. JamesBurger

    60,305

    Master

    0 points yesterday

    Profile
    Rank: Sage
  20. sedgwick

    52,750

    Master

    1,600 points yesterday

    Profile
    Rank: Genius
  21. emoreau

    50,917

    Master

    0 points yesterday

    Profile
    Rank: Genius
  22. ged325

    50,311

    Master

    2,000 points yesterday

    Profile
    Rank: Genius
  23. anuradhay

    49,977

    2,500 points yesterday

    Profile
    Rank: Guru
  24. techChallenger1

    47,638

    0 points yesterday

    Profile
    Rank: Guru
  25. mas_oz2003

    43,540

    0 points yesterday

    Profile
    Rank: Genius

Hall Of Fame