Это не поведение во время выполнения, а разрешение перегрузки метода времени компиляции и ковариация:
context.RemoveRange(existing);
RemoveRange
метод имеет две перегрузки:
RemoveRange(IEnumerable<object> entities)
и
RemoveRange(params object[] entities)
Наличие ограничения класса позволяет компилятору C # выбирать перегрузку с помощью IEnumerable<object>
- поскольку ICollection<T>
равно IEnumerable<T>
, а IEnumerable<T>
для ссылочного типа T
ковариантно, следовательно, IEnumerable<object>
.
Без ограничения класса единственными доступными параметрами является метод с аргументом params object[]
.И тут возникает один из недостатков / побочных эффектов / ловушек конструкции params object[]
- каждый отдельный аргумент arg
с типом, отличным от object[]
, обрабатывается как object
и передается неявно как new object[] { arg }
.
Итак, в первом случае фактический вызов -
context.RemoveRange((IEnumerable<object>)existing);
, а в последнем случае -
context.RemoveRange(new object[] { existing });
Другими словами, список передается как объект, что приводит крассматриваемое исключение времени выполнения.
То же самое относится ко всем другим Range
методам класса DbContext
- AddRange
, UpdateRange
и AttachRange
.