Skip to content

[API Proposal]: Make it easy to get the default value of a type given a System.Type #90697

@Neme12

Description

@Neme12

As an alternative to RuntimeHelpers.GetUninitializedObject(), expose a new method to make this easier and more discoverable.

API

namespace System;

public static partial class Activator
{
    // Same as `type.IsValueType ? RuntimeHelpers.GetUninitializedObject(type) : null`:
+   public static object? CreateDefaultValue(Type type); 

    // For consistency with above support generics; same as C#'s default(T):
+   public static T? CreateDefaultValue<T>(); 
}

Examples

int i1 = (int)Activator.CreateDefaultValue(typeof(int)); // returns 0
int i2 = Activator.CreateDefaultValue<int>(); // returns 0

object? o1 = Activator.CreateDefaultValue(typeof(object)); // returns null
object? o2 = Activator.CreateDefaultValue<object>(); // returns null

Original issue

Background and motivation

When I have a System.Type and want to get its default value, the usual answer has always been to use code like this:

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

e.g. see https://stackoverflow.com/questions/325426/programmatic-equivalent-of-defaulttype

However, C# now allows explicit parameterless constructors on structs, so new T() can now be different from default(T) for structs, and therefore the code above is incorrect because it would invoke the constructor as opposed to getting the default, uninitialized value. It's also not clear what a proper way to do this would look like and it doesn't seem to be trivial at all. That's why I'm proposing an API for this.

API Proposal

namespace System
{
    public abstract partial class Type
    {
        public virtual object? GetDefaultValue();
        // or as a property to match the existing ParameterInfo.DefaultValue
        public virtual object? DefaultValue { get; }
    }
}

API Usage

// `deconstructMethod` has out parameters:
// public void Deconstruct(out bool hasValue, out T value);
var deconstructMethod = type.GetMethod(...);
var parameters = new object?[] { default(bool), underlyingType.DefaultValue };
deconstructMethod.Invoke(value, parameters);
// use parameters

Alternative Designs

No response

Risks

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions