46

If I want a method that returns the default value of a given type and the method is generic I can return a default value like so:

public static T GetDefaultValue()
{
  return default(T);
}

Can I do something similar in case I have the type only as a System.Type object?

public static object GetDefaultValue(Type type)
{
  //???
}
Patrick Klug
  • 14,056
  • 13
  • 71
  • 118

3 Answers3

75

Since you really only have to worry about value types (reference types will just be null), you can use Activator.CreateInstance to call the default constructor on them.

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

Edit: Jon is (of course) correct. IsClass isn't exhaustive enough - it returns False if type is an interface.

Mark Brackett
  • 84,552
  • 17
  • 108
  • 152
  • 22
    Better to use !type.IsValueType, to cope with interfaces. – Jon Skeet Aug 15 '09 at 06:31
  • 1
    Suggestion to improve answer: add `this` to the parameter to make it an extension method. – Shaul Behr Dec 13 '18 at 08:46
  • There appears to be a new method in dotnet core 2 called `Type.GetDefaultValue()`, but it doesn't appear in any MSDN documentation. – Ryan Jul 16 '19 at 04:18
  • 1
    Also note, this actually has an edge case: https://github.com/dotnet/corefx/issues/31646#issuecomment-411443507 If the struct has a default constructor, this will run that constructor. `System.Runtime.Serialization.FormatterServices.GetUninitializedObject` is actually more accurate. – Ryan Jul 16 '19 at 04:20
7

Here is how I normally do it. This avoids the whole 'IsValueType' or searching for constructors issues altogether.

public static object MakeDefault(this Type type)
{
    var makeDefault = typeof(ExtReflection).GetMethod("MakeDefaultGeneric");
    var typed = makeDefault.MakeGenericMethod(type);
    return typed.Invoke(null, new object[] { });
}

public static T MakeDefaultGeneric<T>()
{
    return default(T);
}
jonfuller
  • 617
  • 8
  • 8
  • Can you explain how this is different/better/worse than Mark Brackett answer? – rollsch Mar 20 '17 at 01:55
  • 1
    I can't say it's better or worse; depends on your needs I suppose. My answer is almost certainly slower without any caching. The one thing I particularly like about this solution, is that it does use the built in language feature that we're trying to emulate; rather than simulate it. – jonfuller Mar 21 '17 at 11:29
0

Without a generic, you can't guarantee that the type has a parameterless constructor, but you can search for one using reflection:

public static object GetDefaultValue(Type type)
{
    ConstructorInfo ci = type.GetConstructor( new Type[] {} );
    return ci.Invoke( new object[] {} );
}

I tried this in a console app, and it returns a "default" instance of the class — assuming it's a class. If you need it to work for reference types as well, you'll need an additional technique.

harpo
  • 41,820
  • 13
  • 96
  • 131
  • 3
    THe default value for reference type is null, and not an instance of the class. So if he does what you suggest GetDefault(T) will return null while GetDefault(Type) will try to make an instance if possible, which is wrong. You technique is not useless but I guess it is more like a "T GetInstance(T) where T : new() {return new T();}" type of method. – JohannesH Aug 15 '09 at 05:22