Programmatic equivalent of default(Type)

C#ReflectionDefault

C# Problem Overview


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?

C# Solutions


Solution 1 - C#

  • 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

Solution 2 - C#

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);
    }

Solution 3 - C#

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.

Solution 4 - C#

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.

Solution 5 - C#

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);
    }

Solution 6 - C#

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;
        }
    }
}

Solution 7 - C#

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.");

Solution 8 - C#

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;
    }

Solution 9 - C#

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..

Solution 10 - C#

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;
		}
	}
}

Solution 11 - C#

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));
}

Solution 12 - C#

 /// <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;
    }

Solution 13 - C#

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questiontags2kView Question on Stackoverflow
Solution 1 - C#Dror HelperView Answer on Stackoverflow
Solution 2 - C#DrakarahView Answer on Stackoverflow
Solution 3 - C#JoelFanView Answer on Stackoverflow
Solution 4 - C#casperOneView Answer on Stackoverflow
Solution 5 - C#Rob Fonseca-EnsorView Answer on Stackoverflow
Solution 6 - C#cuftView Answer on Stackoverflow
Solution 7 - C#BSick7View Answer on Stackoverflow
Solution 8 - C#kpollockView Answer on Stackoverflow
Solution 9 - C#Konstantin IsaevView Answer on Stackoverflow
Solution 10 - C#Paul FlemingView Answer on Stackoverflow
Solution 11 - C#thomasgallikerView Answer on Stackoverflow
Solution 12 - C#Kaz-LAView Answer on Stackoverflow
Solution 13 - C#dancer42View Answer on Stackoverflow