7

In c# I can use default(T) to get the default value of a type. I need to get the default type at run time from a System.Type. How can I do this?

E.g. Something along the lines of this (which doesn't work)

var type = typeof(int);
var defaultValue = default(type);
John Mills
  • 10,020
  • 12
  • 74
  • 121

3 Answers3

9

For a reference type return null, for a value type, you could try using Activator.CreateInstance or calling the default constructor of the type.

public static object Default(Type type)
{
   if(type.IsValueType)
   {
      return Activator.CreateInstance(type);
   }

   return null;
}
Julien Hoarau
  • 48,964
  • 20
  • 128
  • 117
  • 1
    Shortly after writing my question I came up with `return Expression.Lambda>(Expression.Convert(Expression.Default(type), typeof (object))).Compile()();`, but yours is so much nicer. – John Mills Sep 14 '10 at 09:08
  • @Giddy: that would be a very expensive way to do it, since you're compiling the expression tree to IL (and then JIT will have to compile it to native) on every invocation. – Pavel Minaev Sep 14 '10 at 17:29
  • Yes, I agree. Which is why I'm not using it, and am using madgnome's solution instead. Although, it was the shorter and more readable code, not performance, that pushed me to use his one. Performance isn't too big of a deal for my scenario. – John Mills Sep 14 '10 at 22:20
6

If you're trying to build an expression tree, use Expression.Default:

Expression expression = Expression.Default(type);

One other way you could do this fairly easily would be:

object defaultValue = Array.CreateInstance(type, 1).GetValue(0);

Ugly, but it'll work :) Note that it's hard to get the default value of a nullable type, as it will always be boxed to a null reference.

As noted in comments, there are some obscure scenarios (void and pointer types) where these aren't equivalent, but they're corner cases :)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    I'm generating expression trees for use with Mindscape Lightspeed, but their query provider doesn't support `DefaultExpression`, so I need the actual value to put inside a `ConstantExpression`. – John Mills Sep 14 '10 at 09:11
  • Slightest of the slightest nitpickings, the behviour is different for pointer types. `default(int*)` returns `IntPtr.Zero`, while `Default(typeof(int*))` throws. Another obscure area I have found out is for `System.Void`, you cannot do `default(void)` whereas `Default(typeof(void))` returns null. No biggie, just in case anyone wants to take care of.. – nawfal Jul 05 '16 at 12:44
  • @nawfal: Added a note to that effect, thanks. – Jon Skeet Jul 05 '16 at 12:51
4

That's pretty easy, you just have 2 cases to consider:

  • reference types: the default value is always null
  • value types: you can easily create an instance using Activator.CreateInstance

    public static object GetDefaultValue(Type type)
    {
        if (type.IsValueType)
        {
            return Activator.CreateInstance(type);
        }
        else
        {
            return null;
        }
    }
    

You could also consider using FormatterServices.GetUninitializedObject instead of Activator.CreateInstance, it's probably faster.

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • Have you tried running your code? It won't work, and the reason is that value types do not (normally) have a default constructor. They do in C#, but it's a fiction; on CLR level there is none, and `initobj` is used in IL. – Pavel Minaev Sep 14 '10 at 09:01
  • @Pavel, you're right, I never realized that there wasn't a real default constructor... I changed it to Activator.CreateInstance, and it works fine – Thomas Levesque Sep 14 '10 at 09:07