List<User> users = GetUsers();
// Antiga API - verbose e menos performática
var dtos = CollectionMapper.MapToList(users, Mapper.To<UserDto>);
var array = CollectionMapper.MapToArray(users, Mapper.To<UserDto>);List<User> users = GetUsers();
// Nova API - limpa e com Span!
var dtos = Mapper.ToList<UserDto>(users); // ⚡ Auto-otimizado
var array = Mapper.ToArray<UserDto>(users); // ⚡ Span zero-copy// Antes: 60 caracteres
CollectionMapper.MapToList(users, Mapper.To<UserDto>)
// Agora: 33 caracteres - 45% MENOR!
Mapper.ToList<UserDto>(users)A nova API detecta automaticamente o tipo de coleção e usa o caminho mais rápido:
// List<T> → Usa CollectionsMarshal.AsSpan (NET8+)
List<User> list = GetList();
var dtos1 = Mapper.ToList<UserDto>(list); // ⚡ Fast-path com Span
// Array → Usa AsSpan() zero-copy
User[] array = GetArray();
var dtos2 = Mapper.ToList<UserDto>(array); // ⚡ Fast-path com Span
// IEnumerable → Materializa com foreach otimizado
IEnumerable<User> enumerable = GetEnumerable();
var dtos3 = Mapper.ToList<UserDto>(enumerable); // Slow-path (inevitável)Para cenários de máxima performance:
User[] users = GetUsers();
Span<UserDto> destination = stackalloc UserDto[users.Length];
// TRUE zero allocation - tudo na stack!
Mapper.ToSpan(users.AsSpan(), destination);BenchmarkDotNet v0.13.12
| Method | Items | Mean | Allocated |
|-------------------------|-------|-----------|-----------|
| ToList_List_NET8 | 100 | 1.234 μs | 3.2 KB | ⚡ FASTEST
| ToList_Array | 100 | 1.289 μs | 3.2 KB | ⚡ FASTEST
| CollectionMapper (old) | 100 | 1.456 μs | 3.3 KB | Slower
| ToSpan (zero alloc) | 100 | 1.123 μs | 0 B | ⚡⚡⚡ ULTIMATE
// ✅ Use para 95% dos casos
var dtos = Mapper.ToList<UserDto>(users);// ✅ Use quando a API espera array
UserDto[] array = Mapper.ToArray<UserDto>(users);// ✅ Use em hot paths, loops, processamento intensivo
Span<UserDto> buffer = stackalloc UserDto[100];
Mapper.ToSpan(users.AsSpan(), buffer);
// Processe buffer sem allocation// ⚠️ Ainda funciona, mas ToList/ToArray são melhores
// Use apenas se precisar de compatibilidade com código antigo
var dtos = CollectionMapper.MapToList(users, Mapper.To<UserDto>);// Se você conhece o tamanho, use ToSpan para zero alloc
var buffer = ArrayPool<UserDto>.Shared.Rent(users.Count);
try
{
Mapper.ToSpan(users.AsSpan(), buffer);
// Use buffer...
}
finally
{
ArrayPool<UserDto>.Shared.Return(buffer);
}// ✅ BOM - Fast-path com Span
List<User> list = GetListFromDatabase();
var dtos = Mapper.ToList<UserDto>(list);
// ❌ EVITE - Materializa IEnumerable primeiro
IEnumerable<User> query = GetQueryFromDatabase();
var dtos2 = Mapper.ToList<UserDto>(query); // Slow
// ✅ MELHOR - Materialize para List primeiro
var list2 = query.ToList();
var dtos3 = Mapper.ToList<UserDto>(list2); // Fast-path!const int BatchSize = 1000;
Span<UserDto> batch = stackalloc UserDto[BatchSize];
for (int i = 0; i < users.Length; i += BatchSize)
{
var sourceBatch = users.AsSpan(i, Math.Min(BatchSize, users.Length - i));
var destBatch = batch[..sourceBatch.Length];
Mapper.ToSpan(sourceBatch, destBatch);
// Processe batch (zero allocation!)
ProcessBatch(destBatch);
}| Característica | ToList/ToArray | MapToList/MapToArray | ToSpan |
|---|---|---|---|
| Sintaxe | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| Performance | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Facilidade | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
| Allocations | Mínimo | Mínimo | ZERO |
Recomendação: Use ToList<T>() e ToArray<T>() como padrão. Reserve ToSpan() para hot paths críticos.