-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Description
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