dotnet / dotnet/aspnetcore

Some call sites to Activator.CreateInstance incorrectly assume it always returns default(T) for value types

Open
#28,307 2 comments 0 reactions 0 assignees View on GitHub
area-mvc bug feature-mvc-execution-pipeline
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 10h
Merged PRs (30d)
281

Description

There are a few call sites around the aspnet code base that use `Activator.CreateInstance` as a cheap way to create a _default(T)_. This isn't quite correct logic, as `Activator.CreateInstance(Type)` will invoke the default (parameterless) ctor for a value type if it exists.

https://github.com/dotnet/aspnetcore/blob/d2e85be7972d88378ec698449593a63ecb9c1dfe/src/Mvc/Mvc.Core/src/Formatters/InputFormatter.cs#L36-L39

https://github.com/dotnet/aspnetcore/blob/d2e85be7972d88378ec698449593a63ecb9c1dfe/src/Mvc/Mvc.Core/src/Infrastructure/ParameterDefaultValues.cs#L34-L37

https://github.com/dotnet/aspnetcore/blob/d2e85be7972d88378ec698449593a63ecb9c1dfe/src/Mvc/Mvc.Core/src/ModelBinding/ModelBindingHelper.cs#L673-L677

https://github.com/dotnet/aspnetcore/blob/d2e85be7972d88378ec698449593a63ecb9c1dfe/src/Shared/ParameterDefaultValue/ParameterDefaultValue.cs#L42-L45

(There may be other examples; that's just one set of matches I saw when looking at `Activator.CreateInstance(Type)` callers.)

Currently the logic of `Activator.CreateInstance` (for value types) is:

* If the given type is `Nullable`, returns _null_.
* If the given type has no parameterless ctor, returns a boxed instance of the value type with all fields zero-inited.
* If the given type has a parameterless ctor, returns a boxed instance of the value type where the ctor has been invoked.
* `Activator.CreateInstance` behaves similarly, but it unboxes the value type before returning it.

And the logic of `RuntimeHelpers.GetUninitializedObject` (for value types) is:

* If the given type is `Nullable`, returns a boxed instance of `T` with all fields zero-inited.
* Otherwise, returns a boxed instance of the value type with all fields zero-inited.

See also https://github.com/dotnet/csharplang/issues/99 and https://github.com/dotnet/csharplang/issues/146, which may introduce the ability to write explicit default struct ctors from within C# and which may affect what it means for a struct to have a "default" value. There's no immediate action required, but you may want to keep an eye on these issues.

Found while working on https://github.com/dotnet/runtime/issues/36194.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.