Sunday 22 February 2015

Generic Fun : Generic Implicit Operators

Just playing around with generics, thinking about using them for things like lazy loading wrappers and potentially for dirty tracking and things like that. Lets start with a simple generic wrapper that doesn't do anything.
 public class Wrapper<T>  
 {  
     public T Value { get; }  
   
     public Wrapper(T value)  
     {  
         Value = value;  
     }  
 }  
(Using C# 6)

One of the problems is that you always have to add in a .Value for reading out and new Wrapper<T>(someData) for creating. One solution to this is to use implicit operators. Thus allowing you to create by just assigning a instance of T to the variable, and read out by assigning in to a T variable.
 public class Wrapper<T>  
 {  
     private T _value;  
   
     public Wrapper(T value)  
     {  
         _value = value;  
     }  
   
     public static implicit operator Wrapper<T>(T value)  
     {  
         return new Wrapper<T>(value);  
     }  
   
     public static implicit operator T(Wrapper<T> value)  
     {  
         return value._value;  
     }  
 }  

This will allow you to do things like this:
 Wrapper<string> textWrapper = "Text";  
 string text = textWrapper;  
   
 Wrapper<int> numberWrapper = 23;  
 int number = numberWrapper;  

There are some drawbacks to this, as if you are reading in to implicitly typed local variables (var), it would treat it as a Wrapper<T> unless you specify the type of the variable. Causing the properties of T not to be available without accessing the value of the wrapper putting in another variable.

It could be useful to help reduce the amount of code you need to write when using a generic wrapper, I was thinking maybe this could be used for lazy loading?
 public class LazyLoaded<T>  
 {  
     private T _value;  
     private bool _loaded;  
   
     public LazyLoaded(T value)  
     {  
         _value = value;  
     }  
   
     public T Value()  
     {  
         if (!_loaded)  
         {  
             // Load data  
             _loaded = true;  
         }  
   
         return _value;  
     }  
   
     public static implicit operator LazyLoaded<T>(T value)  
     {  
         return new LazyLoaded<T>(value);  
     }  
   
     public static implicit operator T(LazyLoaded<T> value)  
     {  
         return value._value;  
     }  
 }  

Even if it's not useful, still interesting :)