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) :-
Nullable<int> q1;
if(q1.HasValue)
Console::WriteLine(q1.Value);
else
Console::WriteLine("It's null");
q1 = Nullable<int>(99);
if(q1.HasValue)
q1 = Nullable<int>(q1.Value + 1);
Nullable<int> q2 = q1;
if( q2.HasValue )
{
q2 = Nullable<int>();
}
Not very convenient, is it? Now look at this C++ code :-
CNullable<int> q1;
if(q1.HasValue)
Console::WriteLine(q1.Value);
else
Console::WriteLine("It's null");
q1 = 99;
(*q1)++;
CNullable<int> q2 = q1;
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.