Tuesday, August 2, 2011

Getting the default value of a type during runtime

As you cannot get the default value of a type during runtime, i.e. you cannot do this:
@{
    Type tx = ...;
    @(default(tx))
}


You must devise this:
public static class Helper
{
    public static object GetDefault(this Type type)
    {
        if (type.IsValueType)
        {
            return Activator.CreateInstance(type);
        }
        return null;
    }
}


But the compiler will complain an error at this:
default(int) == typeof(int).GetDefault()

Operator '==' cannot be applied to operands of type 'int' and 'object'


Must use this code(no errors, compile-time-wise and runtime-wise)
default(int).Equals(typeof(int).GetDefault())


But if you use Equals (has no error nor warning on compile time) on non-value type, it will cause an error during runtime, cannot use any method on null value
default(string).Equals(typeof(string).GetDefault())

Here's the error on runtime
Object reference not set to an instance of an object.


So you have to do this on non-value type:
default(string) == typeof(string).GetDefault()

But you can't use == operator on value types. Figuring out if a type is value type or not is not, could only result to clumsy-looking code, it could be a guesswork too, e.g. DateTime is not a class, it is struct(hence value type), and as such, must use default(DateTime).Equals. And inferring value-type-ness of a type during runtime is a chore too. These tests returns true:

@(default(string) == typeof(string).GetDefault())
@(default(int).Equals(typeof(int).GetDefault()))    
@(default(bool).Equals(typeof(bool).GetDefault()))
@(default(DateTime).Equals(typeof(DateTime).GetDefault()))
@(default(Guid).Equals(typeof(Guid).GetDefault()))    
@(default(DataTable) == typeof(DataTable).GetDefault())



Fortunately there's an object.Equals method, guessworks is not needed anymore. These tests returns true:

@(object.Equals(default(string), typeof(string).GetDefault()))
@(object.Equals(default(int), typeof(int).GetDefault()))
@(object.Equals(default(bool), typeof(bool).GetDefault()))
@(object.Equals(default(DateTime), typeof(DateTime).GetDefault()))
@(object.Equals(default(Guid), typeof(Guid).GetDefault()))    
@(object.Equals(default(DataTable), typeof(DataTable).GetDefault()))

What's those at-signs in our code? Those are razor tags. It's way shorter than Console.WriteLine, easier for quick-testing codes. Razor is the new Console.WriteLine :-)

1 comment:

  1. Consider my solution at http://stackoverflow.com/questions/2490244/default-value-of-a-type/7881481#7881481. I believe it addresses all the concerns noted here.

    Mark

    ReplyDelete