Default(T) In Generics

"Default" represents the default value of T parameter in generics instructions. In several cases, the default keyword is absolutely unknown and we think it’s unnecessary or its functionality makes it null. There are many development moments with the generics classes where default keyword can be useful.

Default keyword can make our work easier and can make the code safer.

Default(T)

This keyword returns the default value of type parameter.

These are the default values for the more important types inside of CLR,

  • Classes - null
  • Nullable<T> - null
  • Numerics structs (int, double, decimal, etc) - 0
  • DateTime structs - 01/01/0001.
  • Char structs    - empty char.
  • Bool structs - false

Evaluation initializes T parameters

This is a very simple generic method example. This method has two ref parameters of T type and changes your values in the implementation.

  1. public static void ChangeValues<T>(ref T a, ref T b)  
  2. {  
  3.     T _a = a;  
  4.     T _b = b;  
  5.    
  6.     a = _b;  
  7.     b = _a;  
  8. }  

The ChangeValues method doesn't have a generic restriction filter so that T will be any type (reference type or value type)

If necessary validate if the parameters have been initialized (has a valid value different to initialize value), add a validation chunk,

  1. public static void ChangeValues<T>(ref T a, ref T b)  
  2. {  
  3.    
  4.     if(a.Equals(null) || b.Equals(null))  
  5.     {  
  6.         throw new ArgumentException("....");  
  7.     }  
  8.    
  9.     T _a = a;  
  10.     T _b = b;  
  11.    
  12.     a = _b;  
  13.     b = _a;  
  14. }  

We have a problem, because this implementation doesn’t verify the default value types.

It will be an incorrect execution:

  1. static void Main(string[] args)  
  2. {  
  3.     DateTime a = new DateTime();  // bad value  
  4.     DateTime b = DateTime.Today;  
  5.    
  6.     System.Console.WriteLine($"a --> {a}");  
  7.     System.Console.WriteLine($"b --> {b}");  
  8.    
  9.     System.Console.WriteLine();  
  10.    
  11.     ChangeValues(ref a, ref b);  
  12.    
  13.     System.Console.WriteLine($"a --> {a}");  
  14.     System.Console.WriteLine($"b --> {b}");  
  15.    
  16.     System.Console.Read();  
  17. }  

Console output

Console output

To correct this bug, we will use a new method version with the default keyword inclusion,

  1. public static void NewChangeValues<T>(ref T a, ref T b)  
  2. {  
  3.    
  4.     if (a.Equals(default(T)) || b.Equals(default(T)))  
  5.     {  
  6.         throw new ArgumentException("....");  
  7.     }  
  8.    
  9.     T _a = a;  
  10.     T _b = b;  
  11.    
  12.     a = _b;  
  13.     b = _a;  
  14. }  

Create Empty Instance

Another example could be the possibility to create empty instance of T types without reflection (Activator).

  1. public T  CreateEmptyInstace<T>(T item)  
  2. {  
  3.     //var result = Activator.CreateInstance<T>(); ïƒ  Expression  
  4.     var result = default(T);  
  5.    
  6.     return result;  
  7. }  

Reset Generics Instances

Another use case for Default(T) could be for reset instance of generics objects.

  1. public void ResetValue<T>(ref T item)  
  2. {  
  3.     item = default(T);  
  4. }