为什么 AutoMapper 会多次枚举一个 IEnumerable?
Why is AutoMapper enumerating an IEnumerable multiple times?
我们 运行 解决了性能问题并将其追踪到 AutoMapper 在 IEnumerable 上枚举两次。
通过简单地向 AutoMapper 提供一个列表或数组,它很容易在我们这边修复,但我仍然很好奇这是否是预期的行为。
以下最小重现测试失败::
[Test]
public void AutoMapper_Should_Not_Enumerate_Multiple_Times()
{
var counter = 0;
var values = Enumerable.Range(0, 3).Select(_ => counter++);
var mapper = new Mapper(new MapperConfiguration(_ => { }));
var dest= mapper.Map<int[]>(values);
Assert.Equal(3, counter);
}
Result: Counter = 6, dest = [3,4,5],表示IEnumerable被迭代了两次,返回了第二次迭代
我尝试在 AutoMapper 中调试它,但我只发现某些东西首先调用 Count() 然后迭代:
这是预期的行为吗? IEnumerable 如何或在何处映射到数组以及为什么在迭代之前调用 Count()?
这是由 ArrayMapper 实现的,实现是功能上 这个:
var count = source.Count();
var array = new TDestination[count];
int i = 0;
foreach (var item in source)
array[i++] = newItemFunc(item, context);
return array;
我们 运行 解决了性能问题并将其追踪到 AutoMapper 在 IEnumerable 上枚举两次。 通过简单地向 AutoMapper 提供一个列表或数组,它很容易在我们这边修复,但我仍然很好奇这是否是预期的行为。
以下最小重现测试失败::
[Test]
public void AutoMapper_Should_Not_Enumerate_Multiple_Times()
{
var counter = 0;
var values = Enumerable.Range(0, 3).Select(_ => counter++);
var mapper = new Mapper(new MapperConfiguration(_ => { }));
var dest= mapper.Map<int[]>(values);
Assert.Equal(3, counter);
}
Result: Counter = 6, dest = [3,4,5],表示IEnumerable被迭代了两次,返回了第二次迭代
我尝试在 AutoMapper 中调试它,但我只发现某些东西首先调用 Count() 然后迭代:
这是预期的行为吗? IEnumerable 如何或在何处映射到数组以及为什么在迭代之前调用 Count()?
这是由 ArrayMapper 实现的,实现是功能上 这个:
var count = source.Count();
var array = new TDestination[count];
int i = 0;
foreach (var item in source)
array[i++] = newItemFunc(item, context);
return array;