Nullable Types

written by Ryan Olshan on Sunday, January 01 2006

One of the weirder features in C# 2.0 is nullable types. My thinking is as follows: Why complicate things with Nullable<T>, or its shorter version of DataType? (i.e. int?), instead of allowing null values to be assigned to those data types that don't have any way of handling null? Maybe it was a matter of not breaking the framework or introducing changes gradually. Also, code such as that below will cause the compiler to error as nullable types and their non-nullable type equivelent are treated as 2 different types.

int? m_Value1; // The shorter version of Nullable<int> m_Value1
m_Value1 = int.Parse(Request.QueryString["SomeNumberParam"]);

int m_Value2;

if (m_Value1 != null) // Nullable types can be checked for null
{
   m_Value2 = m_Value1; // Won't compile
   m_Value2 = (int)m_Value1; // Will compile
}

Hopefully, in the next version of C#, nullable types will be replaced with the ability for their non-nullable versions to handle null, like below:

int m_Value1, m_Value2;
m_Value1 = int.Parse(Request.QueryString["SomeNumberParam"]);

if (m_Value1 != null)
{
   m_Value2 = m_Value1;
}

Do you dare ask what this non-sense looks like in code form? In case you are wondering, I'm using the non-nullable form of the word form. Sorry if I've confused you by including the ? after form in order to form a question. I now present you with non-sense:

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

[Serializable, StructLayout(LayoutKind.Sequential), TypeDependency("System.Collections.Generic.NullableComparer`1"), TypeDependency("System.Collections.Generic.NullableEqualityComparer`1")]
public struct Nullable<T> where T : struct
{
   private bool hasValue;
   internal T value;

   public Nullable(T value)
   {
      this.value = value;
      this.hasValue = true;
   }

   public bool HasValue
   {
      get
      {
         return this.hasValue;
      }
   }

   public T Value
   {
      get
      {
         if (!this.HasValue)
         {
            ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue);
         }
         return this.value;
      }
   }

   public T GetValueOrDefault()
   {
      return this.value;
   }

   public T GetValueOrDefault(T defaultValue)
   {
      if (!this.HasValue)
      {
         return defaultValue;
      }
      return this.value;
   }

   public override bool Equals(object other)
   {
      if (!this.HasValue)
      {
         return (other == null);
      }
      if (other == null)
      {
         return false;
      }
      return this.value.Equals(other);
   }

   public override int GetHashCode()
   {
      if (!this.HasValue)
      {
         return 0;
      }
      return this.value.GetHashCode();
   }

   public override string ToString()
   {
      if (!this.HasValue)
      {
         return "";
      }
      return this.value.ToString();
   }

   public static explicit operator T(Nullable<T> value)
   {
      return value.get_Value();
   }

   public static implicit operator Nullable<T>(T value)
   {
      return new Nullable<T>(value);
   }
}
   

Kick this post on .NET Kicks

Similar Posts

  1. Implicit and Explicit Operators in C#
  2. Nullable type to string function
  3. Strong Coders Generic Data Access Library

Comments

  • XIII on on 1.02.2006 at 12:20 AM

    XIII avatar

    Hi,



    personally I like the new ?? operator in C# 2.0:



    you can use it like this:



    m_Value2 = m_Value1 ?? 0;



    Which is the same like



    if(m_Value1.HasValue)


    m_Value2 = m_Value1.Value;


    else


    m_Value2 = 0;



    In my current project we use nullable types a lot to have an easier mapping between nullable columns in SQL Server 2005.



    Grz, Kris.

  • Ryan Olshan on on 1.02.2006 at 12:38 AM

    Ryan Olshan avatar

    Nice. I hadn't noticed the ?? operator yet. Cool shortcut. I still think an ideal goal by the next version of C# should be to allow structs that don't have the capability to handle nulls to have that functionality. But for now, I guess something is better than nothing. I can live with it.

Post a comment