E ective usage of underlying Nullable C# with Example



E ective usage of underlying Nullable C# with Example

argument 
Any nullable type is a generic type. And any nullable type is a value type. 
There are some tricks which allow to effectively use the result of the Nullable.GetUnderlyingType method when 
creating code related to reflection/code-generation purposes: 
public static class TypesHelper { 
public static bool IsNullable(this Type type) { 
Type underlyingType; 
return IsNullable(type, out underlyingType); 
} 
public static bool IsNullable(this Type type, out Type underlyingType) { 
underlyingType = Nullable.GetUnderlyingType(type); 
return underlyingType != null; 
} 
public static Type GetNullable(Type type) { 
Type underlyingType; 
return IsNullable(type, out underlyingType) ? type : NullableTypesCache.Get(type); 
} 
public static bool IsExactOrNullable(this Type type, Func predicate) { 
Type underlyingType; 
if(IsNullable(type, out underlyingType)) 
return IsExactOrNullable(underlyingType, predicate); 
return predicate(type); 
} 
public static bool IsExactOrNullable(this Type type) 
where T : struct { 
return IsExactOrNullable(type, t => Equals(t, typeof(T))); 
} 
} 
The usage: 
Type type = typeof(int).GetNullable(); 
Console.WriteLine(type.ToString()); 
if(type.IsNullable()) 
Console.WriteLine("Type is nullable."); 
Type underlyingType; 
if(type.IsNullable(out underlyingType)) 
Console.WriteLine("The underlying type is " + underlyingType.Name + "."); 
if(type.IsExactOrNullable()) 
Console.WriteLine("Type is either exact or nullable Int32."); 
if(!type.IsExactOrNullable(t => t.IsEnum)) 
Console.WriteLine("Type is neither exact nor nullable enum."); 
Output: 
System.Nullable`1[System.Int32] 
Type is nullable. 
The underlying type is Int32. 
Type is either exact or nullable Int32. 
Type is neither exact nor nullable enum. 
PS. The NullableTypesCache is defined as follows: 
 

static class NullableTypesCache { 
readonly static ConcurrentDictionary cache = new ConcurrentDictionary(); 
static NullableTypesCache() { 
cache.TryAdd(typeof(byte), typeof(Nullable)); 
cache.TryAdd(typeof(short), typeof(Nullable)); 
cache.TryAdd(typeof(int), typeof(Nullable)); 
cache.TryAdd(typeof(long), typeof(Nullable)); 
cache.TryAdd(typeof(float), typeof(Nullable)); 
cache.TryAdd(typeof(double), typeof(Nullable)); 
cache.TryAdd(typeof(decimal), typeof(Nullable)); 
cache.TryAdd(typeof(sbyte), typeof(Nullable)); 
cache.TryAdd(typeof(ushort), typeof(Nullable)); 
cache.TryAdd(typeof(uint), typeof(Nullable)); 
cache.TryAdd(typeof(ulong), typeof(Nullable)); 
//... 
} 
readonly static Type NullableBase = typeof(Nullable<>); 
internal static Type Get(Type type) { 
// Try to avoid the expensive MakeGenericType method call 
return cache.GetOrAdd(type, t => NullableBase.MakeGenericType(t)); 
} 
} 

0 Comment's

Comment Form

Submit Comment