592

I'm using reflection to loop through a Type's properties and set certain types to their default. Now, I could do a switch on the type and set the default(Type) explicitly, but I'd rather do it in one line. Is there a programmatic equivalent of default?

Pierre Arnaud
  • 10,212
  • 11
  • 77
  • 108
tags2k
  • 82,117
  • 31
  • 79
  • 106

15 Answers15

799
  • In case of a value type use Activator.CreateInstance and it should work fine.
  • When using reference type just return null
public static object GetDefault(Type type)
{
   if(type.IsValueType)
   {
      return Activator.CreateInstance(type);
   }
   return null;
}

In the newer version of .net such as .net standard, type.IsValueType needs to be written as type.GetTypeInfo().IsValueType

Neville Nazerane
  • 6,622
  • 3
  • 46
  • 79
Dror Helper
  • 30,292
  • 15
  • 80
  • 129
  • 24
    This will return a boxed value type and therefore isn't the exact equivalent of default(Type). However, it's as close as you are going to get without generics. – Russell Giddings Jul 07 '11 at 14:27
  • 9
    So what? If you find a type which `default(T) != (T)(object)default(T) && !(default(T) != default(T))` then you have an argument, otherwise it does not matter whether it is boxed or not, since they are equivalent. – Miguel Angelo Oct 11 '12 at 06:14
  • 7
    The last piece of the predicate is to avoid cheating with operator overloading... one could make `default(T) != default(T)` return false, and that is cheating! =) – Miguel Angelo Oct 11 '12 at 06:16
  • 5
    This helped me a lot, but I thought I should add one thing that might be useful to some people searching this question - there's also an equivalent method if you wanted an _array_ of the given type, and you can get it by using `Array.CreateInstance(type, length)`. – Darrel Hoffman Jun 30 '13 at 01:34
  • 4
    Don't you worry about creating an instance of an unknown value type? This may have collateral effects. – ygormutti Oct 14 '13 at 09:08
  • 2
    If defining custom parameterless constructors on structs is allowed (possibly in C# 6), this would stop being the correct solution. – IS4 Apr 26 '15 at 19:21
  • 3
    This does not work for `System.Net.IPAddress`, because that class does not provide a parameterless constructor. `default(IPAddress)` however does work and is `IPAddress.None` . Not sure how to do this with with a runtime type. – Jannes Oct 21 '15 at 10:20
  • 2
    If you're doing an equality comparison on the result of this method for an Enum-based type, note that you can not use the regular == equality operator. See [this question](http://stackoverflow.com/questions/652673/enum-boxing-and-equality) fore more info. – Jax Dec 16 '15 at 16:36
  • 2
    Just a note (on this 7 (!) year old answer): using `Activator.CreateInstance` is a magnitude slower than using reflection with `GetConstructor` to store a reference to the constructor function of any value type (to reuse). Whether it is hidden or not (as with @Jannes example) does not matter. With generics it is a bit more work, but still much faster. Of course, more often than not, people using reflection do not expect speed, but still. – Abel Dec 18 '15 at 23:10
  • Type.IsValueType was removed in DNX 5.0. The solution from drake7707 will still work. – IMLiviu Jan 22 '16 at 06:20
  • 3
    @Jannes why would it not? `IPAddress` is a reference type and hence should just return null? – nawfal Jul 01 '16 at 17:37
  • If you are going to use this code to return a default value from a method (say you are implementing `DispatchProxy`, please remember about handling `void` returning methods properly. For `void` returning methods you should also return `null`. – csharpfolk Dec 23 '18 at 09:19
  • 1
    It doesn't work. It returns null instead of Enum? type of null – Nick Jan 20 '20 at 12:39
  • For reference types, this will return a null of type "object", not a null of type "type". If you need a null of the specified Type object, then return Convert.ChangeType(null, type) instead of just returning null. – dynamichael Jun 22 '20 at 08:36
  • @dynamichael That makes no sense - the return type of `Convert.ChangeType` is `object?` and if you examine the code, you will see it just returns `null`. `null` has no type. – NetMage Oct 06 '22 at 20:13
  • FYI: you can also use the `Activator.CreateInstance` instead. – Arsen Khachaturyan Feb 07 '23 at 17:19
  • 1
    As of C# 10, this answer is not correct. It is now possible to create a struct with a parameterless constructor, and `Activator.CreateInstance` will call that constructor. Try `record struct S() { public int X = 6; }` with `Activator.CreateInstance() == default(S)`. – Tinister Mar 29 '23 at 00:27
117

Why not call the method that returns default(T) with reflection ? You can use GetDefault of any type with:

    public object GetDefault(Type t)
    {
        return this.GetType().GetMethod("GetDefaultGeneric").MakeGenericMethod(t).Invoke(this, null);
    }

    public T GetDefaultGeneric<T>()
    {
        return default(T);
    }
Drakarah
  • 2,244
  • 2
  • 23
  • 23
  • 10
    This is brilliant because it's so simple. While it's not the best solution here, it's an important solution to keep in mind because this technique can be useful in a lot of similar circumstances. – configurator Feb 17 '13 at 12:45
  • If you call the generic method "GetDefault" instead (overloading), do this: this.GetType().GetMethod("GetDefault", new Type[0]). – Stefan Steiger May 07 '13 at 10:50
  • Let GetDefaultGeneric return `object` and you are ready to do some caching for speed. – IS4 Apr 26 '15 at 19:24
  • 4
    Keep in mind, this implementation is much slower (due to reflection) than the accepted answer. It's still viable, but you'd need to setup some caching for the GetMethod()/MakeGenericMethod() calls to improve performance. – Doug Nov 02 '15 at 16:33
  • 2
    It is possible that the type argument is void. E.g. MethodBase.ResultType() of a void method will return a Type object with Name "Void" or with FullName "System.Void". Therefore I put a guard: if (t.FullName=="System.Void") return null; Thanks for the solution. – Valo Mar 23 '17 at 02:24
  • very clever and this works in .net core as well as compare to accepted answer – Atul Chaudhary Jun 05 '17 at 05:04
  • 12
    Better use `nameof(GetDefaultGeneric)` if you can, instead of `"GetDefaultGeneric"` – Mugen Oct 10 '17 at 10:42
97

You can use PropertyInfo.SetValue(obj, null). If called on a value type it will give you the default. This behavior is documented in .NET 4.0 and in .NET 4.5.

bluish
  • 26,356
  • 27
  • 122
  • 180
JoelFan
  • 37,465
  • 35
  • 132
  • 205
  • 8
    For this specific question - looping trough a type's properties AND setting them to "default" - this works brilliantly. I use it when converting from a SqlDataReader to an object using reflection. – Arno Peters Jun 23 '13 at 09:13
58

If you're using .NET 4.0 or above and you want a programmatic version that isn't a codification of rules defined outside of code, you can create an Expression, compile and run it on-the-fly.

The following extension method will take a Type and get the value returned from default(T) through the Default method on the Expression class:

public static T GetDefaultValue<T>()
{
    // We want an Func<T> which returns the default.
    // Create that expression here.
    Expression<Func<T>> e = Expression.Lambda<Func<T>>(
        // The default value, always get what the *code* tells us.
        Expression.Default(typeof(T))
    );

    // Compile and return the value.
    return e.Compile()();
}

public static object GetDefaultValue(this Type type)
{
    // Validate parameters.
    if (type == null) throw new ArgumentNullException("type");

    // We want an Func<object> which returns the default.
    // Create that expression here.
    Expression<Func<object>> e = Expression.Lambda<Func<object>>(
        // Have to convert to object.
        Expression.Convert(
            // The default value, always get what the *code* tells us.
            Expression.Default(type), typeof(object)
        )
    );

    // Compile and return the value.
    return e.Compile()();
}

You should also cache the above value based on the Type, but be aware if you're calling this for a large number of Type instances, and don't use it constantly, the memory consumed by the cache might outweigh the benefits.

casperOne
  • 73,706
  • 19
  • 184
  • 253
  • 6
    Performance for 'return type.IsValueType ? Activator.CreateInstance(type) : null;' is 1000x faster than e.Compile()(); – Cyrus Aug 31 '14 at 19:48
  • @Cyrus And for a value that's cached? – casperOne Sep 02 '14 at 02:24
  • 2
    @Cyrus I am fairly sure it would be the other way round if you cache the `e.Compile()`. That's the whole point of expressions. – nawfal Jul 05 '16 at 08:38
  • Using it with a cache for Types is imho the best solution! – BendEg Aug 04 '17 at 07:44
  • 2
    Ran a benchmark. Obviously, the result of `e.Compile()` should be cached, but assuming that, this method is roughly 14x as fast for e.g. `long`. See https://gist.github.com/pvginkel/fed5c8512b9dfefc2870c6853bbfbf8b for the benchmark and results. – Pieter van Ginkel Jan 30 '18 at 13:59
  • Re "If ... then memory consumed by cache might outweigh benefits". Solution in that case would be an LRU cache, e.g. https://stackoverflow.com/a/3719378/199364 Also, could add a "Clear" method, which you call from any memory cleanup or low memory method you have. – ToolmakerSteve Feb 06 '18 at 03:28
  • 4
    Out of interest, why cache `e.Compile()` rather than `e.Compile()()`? i.e. Can a type's default type change at runtime? If not (as I believe to be the case) you can just store cache the result rather than the compiled expression, which should improve performance further. – JohnLBevan Oct 02 '18 at 13:19
  • 4
    @JohnLBevan - yes, and then it won't matter what technique you use to get the result - all will have extremely fast amortised performance (a dictionary lookup). – Daniel Earwicker Oct 02 '18 at 13:36
41

Why do you say generics are out of the picture?

    public static object GetDefault(Type t)
    {
        Func<object> f = GetDefault<object>;
        return f.Method.GetGenericMethodDefinition().MakeGenericMethod(t).Invoke(null, null);
    }

    private static T GetDefault<T>()
    {
        return default(T);
    }
Rob Fonseca-Ensor
  • 15,510
  • 44
  • 57
  • Cannot resolve symbol Method. Using a PCL for Windows. – Cœur Jun 14 '14 at 13:43
  • 1
    how expensive is it to create the generic method at run time, and then use it several thousand times in a row? – C. Tewalt Sep 03 '14 at 17:11
  • 1
    I was thinking about something like this. Best and most elegant solution for me. Works even on Compact Framework 2.0. If you are worried about performance, you can always cache generic method, can't you? – Bart Oct 27 '15 at 20:26
  • This solution suits exactly! Thanks! – Lachezar Lalov Oct 12 '18 at 13:12
28

This is optimized Flem's solution:

using System.Collections.Concurrent;

namespace System
{
    public static class TypeExtension
    {
        //a thread-safe way to hold default instances created at run-time
        private static ConcurrentDictionary<Type, object> typeDefaults =
           new ConcurrentDictionary<Type, object>();

        public static object GetDefaultValue(this Type type)
        {
            return type.IsValueType
               ? typeDefaults.GetOrAdd(type, Activator.CreateInstance)
               : null;
        }
    }
}
ErikE
  • 48,881
  • 23
  • 151
  • 196
cuft
  • 281
  • 3
  • 2
  • 3
    A short hand version of the return: `return type.IsValueType ? typeDefaults.GetOrAdd(type, Activator.CreateInstance) : null;` – Mark Whitfeld Jan 23 '13 at 14:08
  • 4
    What about mutable structs? Do you know that it is possible (and legal) to modify fields of a boxed struct, so that the data change? – IS4 Apr 26 '15 at 19:23
  • @IllidanS4 as the method's name implies this is only for default ValueType's values. – aderesh Jan 24 '18 at 16:21
7

The chosen answer is a good answer, but be careful with the object returned.

string test = null;
string test2 = "";
if (test is string)
     Console.WriteLine("This will never be hit.");
if (test2 is string)
     Console.WriteLine("Always hit.");

Extrapolating...

string test = GetDefault(typeof(string));
if (test is string)
     Console.WriteLine("This will never be hit.");
BSick7
  • 575
  • 4
  • 13
  • 16
    true, but that holds for default(string) as well, as every other reference type... – TDaver Jan 21 '11 at 14:12
  • string is an odd bird - being a value type that can return null as well. If you want the code to return string.empty just add a special case for it – Dror Helper Jul 07 '11 at 07:09
  • 16
    @Dror - string is an immutable reference type, not a value type. – ljs Aug 18 '11 at 16:01
  • @kronoz You're right - I meant that string can be handled by returning string.empty or null according to need. – Dror Helper Aug 21 '11 at 06:40
7

There are a couple answers here that use Activator.CreateInstance. However, since those answers were made, C# and .NET made changes that allow users to define structs with parameterless constructors (documentation link). Activator.CreateInstance will execute such a parameterless constructor if defined, and you will no longer get the default instance.

Instead you can use FormatterServices.GetUninitializedObject, like so:

//using System.Runtime.Serialization
public static object GetDefault(Type type)
{
    // it's very important to check IsValueType before calling GetUninitializedObject
    // GetUninitializedObject is valid for reference types, but it will not return null
    if (type.IsValueType)
    {
        return FormatterServices.GetUninitializedObject(type);
    }
    return null;
}

Another option, which you can do as a single-liner, is use Array.CreateInstance:

// works for both reference types and value types
static object GetDefault(Type type) => Array.CreateInstance(type, 1).GetValue(0);
Tinister
  • 11,097
  • 6
  • 35
  • 36
  • 3
    I agree that this should be the preferred way, as it’s also the way [Microsoft’s code does this](https://source.dot.net/#System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs,cccbda6331263481,references). Except they use [`System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject`](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.runtimehelpers.getuninitializedobject), which is also called by FormatterServices.GetUninitializedObject. – ckuri Jun 20 '23 at 20:29
5

I do the same task like this.

//in MessageHeader 
   private void SetValuesDefault()
   {
        MessageHeader header = this;             
        Framework.ObjectPropertyHelper.SetPropertiesToDefault<MessageHeader>(this);
   }

//in ObjectPropertyHelper
   public static void SetPropertiesToDefault<T>(T obj) 
   {
            Type objectType = typeof(T);

            System.Reflection.PropertyInfo [] props = objectType.GetProperties();

            foreach (System.Reflection.PropertyInfo property in props)
            {
                if (property.CanWrite)
                {
                    string propertyName = property.Name;
                    Type propertyType = property.PropertyType;

                    object value = TypeHelper.DefaultForType(propertyType);
                    property.SetValue(obj, value, null);
                }
            }
    }

//in TypeHelper
    public static object DefaultForType(Type targetType)
    {
        return targetType.IsValueType ? Activator.CreateInstance(targetType) : null;
    }
kpollock
  • 3,899
  • 9
  • 42
  • 61
3

Equivalent to Dror's answer but as an extension method:

namespace System
{
    public static class TypeExtensions
    {
        public static object Default(this Type type)
        {
            object output = null;

            if (type.IsValueType)
            {
                output = Activator.CreateInstance(type);
            }

            return output;
        }
    }
}
Paul Fleming
  • 24,238
  • 8
  • 76
  • 113
3

Slight adjustments to @Rob Fonseca-Ensor's solution: The following extension method also works on .Net Standard since I use GetRuntimeMethod instead of GetMethod.

public static class TypeExtensions
{
    public static object GetDefault(this Type t)
    {
        var defaultValue = typeof(TypeExtensions)
            .GetRuntimeMethod(nameof(GetDefaultGeneric), new Type[] { })
            .MakeGenericMethod(t).Invoke(null, null);
        return defaultValue;
    }

    public static T GetDefaultGeneric<T>()
    {
        return default(T);
    }
}

...and the according unit test for those who care about quality:

[Fact]
public void GetDefaultTest()
{
    // Arrange
    var type = typeof(DateTime);

    // Act
    var defaultValue = type.GetDefault();

    // Assert
    defaultValue.Should().Be(default(DateTime));
}
Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
thomasgalliker
  • 1,279
  • 13
  • 19
3

The Expressions can help here:

    private static Dictionary<Type, Delegate> lambdasMap = new Dictionary<Type, Delegate>();

    private object GetTypedNull(Type type)
    {
        Delegate func;
        if (!lambdasMap.TryGetValue(type, out func))
        {
            var body = Expression.Default(type);
            var lambda = Expression.Lambda(body);
            func = lambda.Compile();
            lambdasMap[type] = func;
        }
        return func.DynamicInvoke();
    }

I did not test this snippet, but i think it should produce "typed" nulls for reference types..

Miguel Angelo
  • 23,796
  • 16
  • 59
  • 82
Konstantin Isaev
  • 642
  • 8
  • 14
  • 1
    `"typed" nulls` - explain. What object are you returning? If you return an object of type `type`, but its value is `null`, then it does not - cannot - have any other information other than that it is `null`. You can't query a `null` value, and find out what type it supposedly is. If you DON'T return null, but return .. I don't know what .., then it won't act like `null`. – ToolmakerSteve Feb 06 '18 at 02:57
-1
 /// <summary>
    /// returns the default value of a specified type
    /// </summary>
    /// <param name="type"></param>
    public static object GetDefault(this Type type)
    {
        return type.IsValueType ? (!type.IsGenericType ? Activator.CreateInstance(type) : type.GenericTypeArguments[0].GetDefault() ) : null;
    }
Kaz-LA
  • 226
  • 1
  • 5
  • 2
    Doesn't work for `Nullable` types: it doesn't return the equivalent of `default(Nullable)` which should be `null`. Accepted answer by Dror works better. – Cœur Jun 16 '14 at 00:11
-1

This should work: Nullable<T> a = new Nullable<T>().GetValueOrDefault();

dancer42
  • 179
  • 1
  • 3
-1

If you already create an object, you can try...

var yourObj = new yourObj();
var properties = yourObj.GetType().GetProperties();

foreach (var p in properties)
{
    // you can get default value for each property
    var defaultValue = p.GetValue(yourObj, null);
}
Mina chen
  • 1,604
  • 12
  • 13