65.9K
CodeProject is changing. Read more.
Home

CNullable<T> : A convenient Nullable<T> equivalent class for C++/CLI

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (18 votes)

May 18, 2005

2 min read

viewsIcon

64162

downloadIcon

581

CNullable<T> can be used to represent a value type (or simple native type) such that the type can be nulled. You can also compare it to nullptr using the == and != operators both of which have been overloaded.

Overview

Starting with Whidbey, C# supports nullable types (value types that can also be null) and it does this using the System::Nullable<T> generic class defined in the mscorlib assembly. It also provides a short-cut form, T? var which corresponds to System.Nullable<T> var. Take a look at the following C# code snippet :-

int? q1 = null;

if (q1.HasValue)
    Console.WriteLine(q1.Value);
else
    Console.WriteLine("It's null");    

q1 = 99;
q1++;

int? q2 = q1;
if (q2 != null)
{
    q2 = null;
}

Now, take a look at the corresponding C++ code (C# code in comments) :-

//int? q1 = null;
Nullable<int> q1;

//if (q1.HasValue)
//    Console.WriteLine(q1.Value);
//else
//    Console.WriteLine("It's null");

if(q1.HasValue)
    Console::WriteLine(q1.Value);
else
    Console::WriteLine("It's null");

//q1 = 99;

q1 = Nullable<int>(99);

//q1++;

if(q1.HasValue)
    q1 = Nullable<int>(q1.Value + 1);

//int? q2 = q1;

Nullable<int> q2 = q1;

//if (q2 != null)
//{
//    q2 = null;
//}

if( q2.HasValue )
{
    q2 = Nullable<int>();
}

Not very convenient, is it? Now look at this C++ code :-

//int? q1 = null;
CNullable<int> q1;

//if (q1.HasValue)
//    Console.WriteLine(q1.Value);
//else
//    Console.WriteLine("It's null");

if(q1.HasValue)
    Console::WriteLine(q1.Value);
else
    Console::WriteLine("It's null");

//q1 = 99;

q1 = 99;

//q1++;

(*q1)++;

////int? q2 = q1;

CNullable<int> q2 = q1;

//if (q2 != null)
//{
//    q2 = null;
//}

if(q2 != nullptr)
{
    q2 = nullptr;
}

Well, that's a lot more closer to the C# code as far as ease-of-use is concerned, is it not? That's why I wrote my CNullable<> template ref class for C++/CLI.

Class Reference

template<typename T> ref class CodeProject::Extra::CNullable sealed : INullableValue

CNullable can be used to represent a value type (or simple native type) such that the type can be nulled. You can also compare it to nullptr using the == and != operators both of which have been overloaded.

Constructors

  • CNullable()

    The default constructor creates a CNullable object assigned to nullptr.

    CNullable<char> x1;
  • CNullable(void* p)

    This overload handles the case where a nullptr is passed to the constructor. If the pointer passed is not a nullptr, an InvalidOperationException gets thrown.

    CNullable<double> x2(nullptr);
  • CNullable(const T% t)

    Constructs a CNullable object using the passed in template-argument type.

    CNullable<int> x3(100);
  • CNullable(const CNullable% n)

    Copy constructor.

    CNullable<int> x4(x3);

Operators

  • operator T()

    Converts to type T.

    Note - If the object is currently nulled, an InvalidOperationException is thrown.

    int y = x4;
  • void operator =(void* p)

    Assignment operator that handles the nullptr case.

    Note - If p is a non-null pointer, an InvalidOperationException is thrown.

    x3 = nullptr;
  • const T operator =(const T% t)

    Assignment operator for type T.

    x4 = x3 = 13;
  • T% operator*()

    The underlying type is exposed by overloading the dereference operator.

    x5 = (*x4)++;
  • bool operator ==(void* p)

    Allows == comparison with nullptr.

    if( x5 == nullptr )
    {
    }
  • bool operator !=(void* p)

    Allows != comparison with nullptr.

    if( x5 != nullptr )
    {
    }
  • operator String^()

    Gives the string representation of the type. Internally calls the ToString method.

    Console::WriteLine( (String^)x5 );

Methods

  • virtual String^ ToString() override

    Returns an empty string if the object is currently nulled, else calls ToString on the underlying template-argument type member and returns that string.

    Console::WriteLine( x5.ToString() );
  • Nullable<T> CreateNullable()

    Creates a new Nullable<T> object (useful to interact with .NET code that explicitly expects a Nullable<T>). Normally you'd be able to pass a CNullable object directly since it implements INullableValue.

    Nullable<int> n1 = x5.CreateNullable();
  • static CNullable^ FromNullable(Nullable<T> n)

    Static method to create a new CNullable object from a Nullable<T> object.

    CNullable<int> x6 = CNullable<int>::FromNullable(n1);

Properties

  • property virtual bool HasValue::get

    Implementation of INullableValue::HasValue. Indicates whether the value is valid or whether it's a null-value.

    if(x6.HasValue)
  • property virtual Object^ Value::get

    Implementation of INullableValue::Value. If HasValue is true, it returns the value of the internal template argument type member, otherwise throws an InvalidOperationException exception.

    Console::WriteLine(x6.Value);

History

  • May 18th, 2005 : Article first published on The Code Project.