Это еще один пример params object[]
ловушки.
AddRangeAsync
имеет две перегрузки:
(1)
Task AddRangeAsync(IEnumerable<object> entities, CancellationToken cancellationToken = default)
(2) * * 1 010
Task AddRangeAsync(params object[] entities)
Полагаю, вы хотите вызвать (1), но вопрос в том, какой из них здесь на самом деле называется:
private async Task AddEntities<T>(IEnumerable<T> entities)
{
await AddRangeAsync(entities);
}
Ответ - это зависит!
Если T
имеет ограничение class
, он вызовет (1), в противном случае (2). Это связано с тем, что IEnumerable<T>
является ковариантным только для ссылочных типов, поэтому его можно рассматривать как IEnumerable<object>
, только если компилятор знает, что T
является ссылочным типом, что достигается с помощью ограничения class
.
Похоже, ваш класс не имеет такого ограничения, поэтому компилятор обрабатывает аргумент IEnumerable<T>
как object
(все может быть приведено к object
) и вызывает (2), передавая массив object
одного элемента с аргумент, то есть фактический вызов в этом случае
await AddRangeAsync(new object[] { entities });
, который должен демистифицировать сообщение об ошибке.
С учетом вышесказанного либо используйте ограничение where T : class
, либо Cast
метод расширения:
await AddRangeAsync(entities.Cast<object>());