Open Stabzs opened 3 years ago
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.
Tagging subscribers to this area: @eerhardt, @maryamariyan See info in area-owners.md if you want to be subscribed.
Author: | Stabzs |
---|---|
Assignees: | - |
Labels: | `untriaged`, `area-Extensions-DependencyInjection` |
Milestone: | - |
Other collection types aren't supported at all so that's why you're seeing that behavior. I don't have a strong sense of what is the right thing to do here but this seems like a reasonable thing to expect if you explicitly ask for null instead of empty.
It's also a breaking change so I don't know if we'd do it. We can try with other DI containers as well to see what the behavior looks like there.
One reason for using an empty array is for performance. Take for example https://github.com/dotnet/runtime/pull/49970 where we assume that an array is always passed by DI.
@eerhardt that makes perfect sense from a performance perspective. And in your example, the factory is responsible for the defaulting behavior, not the DI resolver itself.
As far as other IoC containers go, SimpleInjector will not even permit this type of registration due to unregistered dependencies and would require a factory, preventing the issue in the first place.
Autofac has similar behavior of defaulting IEnumerable<T>
, ICollection<T>
and IList<T>
, but not List<T>
or ISet<T>
, which throws an exception during resolution.
LightInject defaults IEnumerable<T>
, ICollection<T>
and IList<T>
, and throws on List<T>
or ISet<T>
.
It seems odd that most container implementations are somewhat inconsistent on how they handle it. If nothing else, it seems like this behavior should potentially expand to other collection types and be better documented. And ideally, a container verification model would prevent this type of odd registration altogether.
Description
When resolving registered instances with
IEnumerable<T> arg1 = null
constructor dependencies,arg1
in unexpectedly initialized to an empty array, instead of null. This is inconsistent with other collection types such asIList<T>
,List<T>
orIList<T>
.This can be recreated with the following code:
in the above example, you would expect that
_defaults
would be used since there is no parameter registered via a factory to the concrete type. However,filters
is passed as an empty array by the IoC resolve call.This does not occur for the following example:
in the second example,
_defaults
is used because filters is correctly passed as null.Configuration
Regression?
This seems consistent across at least .netcore 3.1 and .net 5. I did not test further back.
Other information
This seems to be related to how the constructor/IEnumerable visitor works here: