Daily Knowledge Drop
The List
class has a ConvertAll
method which allows for the conversion of items in a list from one type to another. It operates similar to the LINQ Select
method, but in some use cases will out-perform the LINQ counterpart.
Example
In the below example, we have a List of TypeA
, and would like to convert this list to a a list of TypeB
:
The types:
public class TypeA
{
public string TypeAValue { get; set; }
}
public class TypeB
{
public string TypeBValue { get; set; }
}
Building up a list:
List<TypeA> types = new()
{
new TypeA(),
new TypeA(),
new TypeA(),
new TypeA(),
};
Now that we have a list ot TypeA, we'll look at a couple of ways to convert to a list of TypeB.
LINQ Select
This is the more "traditional" way of converting a list (or IEnumerable) from one type to another:
var typeBList = types
.Select(a => new TypeB { TypeBValue = a.TypeAValue })
.ToList();
Here, the Select will operate on TypeA and instantiate a TypeB for each TypeA, setting the instance properties. The output of this is a list of TypeB.
List ConvertAll
The ConvertAll
usage is similar to that of the Select method:
var typeBList = types
.ConvertAll(type => new TypeB { TypeBValue = type.TypeAValue });
For each item in the list, a TypeB instance is instantiated and the properties set with the values from the TypeA instance.
A note: ConvertAll
is only available on List, so if working with an IEnumerable implementation, the ToList method would need to be called to convert the collection to a list.
Benchmarks
10 Items
Method | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|
LinqSelect | 194.9 ns | 9.99 ns | 29.46 ns | 177.4 ns | 1.00 | 0.00 | 0.0713 | 448 B | 1.00 |
GenericConvertAll | 156.5 ns | 7.43 ns | 21.92 ns | 143.9 ns | 0.82 | 0.16 | 0.0598 | 376 B | 0.84 |
With only 10 items in the list, the the ConvertAll
method is faster, and more memory performant than the LINQ Select
method.
10 000 Items
As the number of items in the list increases, the performance metrics of the two two methods converge:
Method | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|---|
LinqSelect | 175.6 us | 10.90 us | 32.15 us | 189.5 us | 1.00 | 0.00 | 50.7813 | 25.3906 | 312.63 KB | 1.00 |
GenericConvertAll | 174.5 us | 3.42 us | 4.07 us | 173.5 us | 0.97 | 0.15 | 50.7813 | 25.3906 | 312.55 KB | 1.00 |
With 10 000 items, the two methods effectively perform the same, and both use the same amount of memory.
100 000 Items
The same results can be seen with 100 000 records, as was seen with 10 000 record:
Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|---|
LinqSelect | 6.586 ms | 0.1298 ms | 0.2561 ms | 1.00 | 0.00 | 515.6250 | 328.1250 | 179.6875 | 3.05 MB | 1.00 |
GenericConvertAll | 6.236 ms | 0.1199 ms | 0.1970 ms | 0.96 | 0.05 | 515.6250 | 320.3125 | 179.6875 | 3.05 MB | 1.00 |
The two methods effectively perform the same, and both use the same amount of memory.
Notes
If currently using Select
, there is not much reason to update code to switch to ConvertAll
- except if micro performance improvements are critical to your application. However if performance is so critical for the application, LINQ is probably not even being used in the first place.
Having said all that, it is interesting the ConvertAll
method is available and does have performance improvements over using LINQ Select
.
References
Daily Drop 206: 21-11-2022
At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.
The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.