I recently learned about List's .ConvertAll extension. I used it a couple times in code today at work to convert a large list of my objects to a list of some other object. It seems to work really well. However I'm unsure how efficient or fast this is compared to just iterating the list and converting the object. Does .ConvertAll use anything special to speed up the conversion process or is it just a short hand way of converting Lists without having to set up a loop?
相关问题
- Sorting 3 numbers without branching [closed]
- Graphics.DrawImage() - Throws out of memory except
- Why am I getting UnauthorizedAccessException on th
- 求获取指定qq 资料的方法
- How to know full paths to DLL's from .csproj f
It's the second way you described it - basically a short-hand way without setting up a loop.
Here's the guts of
ConvertAll()
:Where
TOutput
is whatever type you're converting to, andconverter
is a delegate indicating the method that will do the conversion.So it loops through the
List
you passed in, running each element through the method you specify, and then returns a newList
of the specified type.No better way to find out than to go directly to the source, literally :)
http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs#dbcc8a668882c0db
As you can see, there's no special magic going on. It just iterates over the list and creates a new item by the converter function that you specify.
To be honest, I was not aware of this method. The more idiomatic .NET way to do this kind of projection is through the use of the
Select
extension method onIEnumerable<T>
like so:source.Select(input => new Something(input.Name))
. The advantage of this is threefold:ConvertAll
is likely a remnant of the pre-C#3.0 days. It's not a very arcane method by any means andConvertAll
is a pretty clear description, but it might still be better to stick to what other people know, which isSelect
.IEnumerable<T>
, whileConvertAll
only works on instances ofList<T>
. It doesn't matter if it's an array, a list or a dictionary,Select
works with all of them.Select
is lazy. It doesn't do anything until you iterate over it. This means that it returns anIEnumerable<TOutput>
which you can then convert to a list by callingToList()
or not if you don't actually need a list. Or if you just want to convert and retrieve the first two items out of a list of a million items, you can simply dosource.Select(input => new Something(input.Name)).Take(2)
.But if your question is purely about the performance of converting a whole list to another list, then
ConvertAll
is likely to be somewhat faster as it's less generic than aSelect
followed by aToList
(it knows that a list has a size and can directly access elements by index from the underlying array for instance).Decompiled using ILSPy:
It doesn't do anything special with regards to conversion (what "special" thing could it do?) It is directly modifying the private
_items
and_size
members, so it might be trivially faster under some circumstances.As usual, if the solution makes you more productive, code easier to read, etc. use it until profiling reveals a compelling performance reason to not use it.
For precise timing in your scenarios you need to measure yourself.
Do not expect any miracles - it have to be O(n) operation since each element need to be converted and added to destination list.
Consider using
Enumerable.Select
instead as it will do lazy evaluation that may allow avoiding second copy of large list, especially you you need to do any filtering of items along the way.