Difference Between Select and Convertall in C#

Difference between Select and ConvertAll in C#

Select is a LINQ extension method and works on all IEnumerable<T> objects whereas ConvertAll is implemented only by List<T>. The ConvertAll method exists since .NET 2.0 whereas LINQ was introduced with 3.5.

You should favor Select over ConvertAll as it works for any kind of list, but they do the same basically.

C# List .ConvertAll Efficiency and overhead

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 on IEnumerable<T> like so: source.Select(input => new Something(input.Name)). The advantage of this is threefold:

  • It's more idomatic as I said, the ConvertAll is likely a remnant of the pre-C#3.0 days. It's not a very arcane method by any means and ConvertAll is a pretty clear description, but it might still be better to stick to what other people know, which is Select.
  • It's available on all IEnumerable<T>, while ConvertAll only works on instances of List<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 an IEnumerable<TOutput> which you can then convert to a list by calling ToList() 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 do source.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 a Select followed by a ToList (it knows that a list has a size and can directly access elements by index from the underlying array for instance).

How to choose between Convert and Select with LINQ to objects?

ConvertAll has been around since .Net 2.0, whereas LINQ is newer. Select appears to be more general, and to make ConvertAll redundant.

I can't think of any situation where you would need to use ConvertAll in new code. Select is better-known, more general, and works with the other features of LINQ (such as direct translation to SQL queries in LINQ to SQL).

linq .Cast or cast inside ConvertAll for a list

TL;DR: ConvertAll makes 1 memory allocation, but .Cast.ToList more than one in most cases.

Most LINQ extensions (like .Cast<T>()) result in a deferred execution IEnumerable<T> that can't be cast to ICollection<T> (can't get the .Count of the result).

When the result can be cast to ICollection<T>, .ToList and .ToArray can make just one memory allocation to copy the elements, but when it can't:

  • initially 4 element buffer array is allocated for non-empty source
  • when space is needed for more elements, new array is allocated with double the size of the previous one
  • elements are copied from the old array to the new one, and the old array is later deallocated by the garbage collector.

Update

Surprisingly, the difference doesn't seem nowhere near as significant as I expected:

method      elapsed             ratio               count

Cast.ToList 00:00:14.4487329 1.3719890831991 123456789
ConvertAll 00:00:10.5312302 0.728868773261865

Cast.ToList 00:00:01.4959734 1.50233158227713 12345678
ConvertAll 00:00:00.9957678 0.665632016125407

Cast.ToList 00:00:00.1252968 2.45948743599897 1234567
ConvertAll 00:00:00.0509442 0.40658878161491

Cast.ToList 00:00:00.0082611 3.99145006839945 123456
ConvertAll 00:00:00.0020697 0.250535515380002

Cast.ToList 00:00:00.0008097 0.620558719826417 12345
ConvertAll 00:00:00.0013049 1.61145104895105

Cast.ToList 00:00:00.0001812 0.193207547169811 1234
ConvertAll 00:00:00.0009378 5.17578125

Cast.ToList 00:00:00.0001433 0.149501661129568 123
ConvertAll 00:00:00.0009587 6.68888888888889

So, race your horses!

int c = 123; var L = Enumerable.Range(0, c).ToList();

GC.Collect(); var sw1 = Stopwatch.StartNew(); L.Cast<object>().ToList(); sw1.Stop();

GC.Collect(); var sw2 = Stopwatch.StartNew(); L.ConvertAll(i => (object)i); sw2.Stop();

MessageBox.Show($"Cast.ToList\t{sw1.Elapsed}\t{(double)sw1.ElapsedTicks / sw2.ElapsedTicks}\n" +
$"ConvertAll \t{sw2.Elapsed}\t{(double)sw2.ElapsedTicks / sw1.ElapsedTicks}");

Array.ConvertAll() and ToArray() method, which is better?

Firstly these aren't equivalent, in one version you are using int.Parse(x) in another Convert.ToInt32(sTemp)

That aside, you have found a perfect example of how to do something more than one way... In programming you will find this a lot.

ConvertAll()

Converts an array of one type to an array of another type.

Select()

Projects each element of a sequence into a new form.

ToArray()

Creates an array from a IEnumerable.

Technically, in combination they produce the same thing, yet got about it in slightly different ways due to the fact they are part of slightly different areas of the BCL that have concerns in slightly different domains.

Personally i don't see ConvertAll used all that much these days as people are very familiar with LINQ and like to chain methods.

As to which is better for performance, we would have to write a lot of tests to figure this out, and it would come down to allocations verse speed per array size per platform. However, i feel the difference would be relatively indistinguishable in day to day, and my guess is you would be struggling to find very much performance difference at all at any significant sigma categorically.

In short, use what You like

Converter And ConvertAll alternative for UWP C#

As you said, in UWP there is no System.Converter and Array.ConvertAll. You can however use the LINQ method Select to do the same work.

Trying to define method similar to ListT.ConvertAll(TOutput)

What you're attempting is called a projection.

An extension method is already included in the .NET Framework to achieve this. IEnumerable.Select, and you can use it in the fashion below.

void Main()
{
List<Foo> foos = new List<Foo>
{
new Foo { Name = "Fu" },
new Foo { Name = "Foe" },
new Foo { Name = "Thumb" }
};

IEnumerable<Bar> bars = foos.Select(foo => new Bar
{
BarId = foo.Id,
Name = foo.Name
});

}

public class Foo
{
public Foo() { Id = Guid.NewGuid().ToString(); }

public string Id { get; set; }
public string Name { get; set; }
}

public class Bar
{
public Bar()
{
this.BarId = Guid.NewGuid().ToString();
this.TimeCreated = DateTime.UtcNow;
}

public string BarId { get; set; }
public string Name { get; set; }
public DateTime TimeCreated { get; set; }
}

Foo to Bar


How it's implemented....

If you wanted to implement a custom solution yourself for the sake of learning, this is how you would go about doing it:

public static class Extensions
{
public static IEnumerable<TDestination> ConvertTo<TFrom, TDestination>(this IEnumerable<TFrom> fromCollection, Func<TFrom, TDestination> expression)
{
List<TDestination> destinationList = new List<TDestination>();
foreach (var element in fromCollection)
{
destinationList.Add(expression.Invoke(element));
}

return destinationList;

}
}

void Main()
{
List<Foo> foos = new List<Foo>
{
new Foo { Name = "Fu" },
new Foo { Name = "Foe" },
new Foo { Name = "Thumb" }
};

IEnumerable<Bar> customBars = foos.ConvertTo(foo => new Bar
{
BarId = foo.Id,
Name = foo.Name
});

}

Why does IList have fewer features than List?

Note that List<> is an implementation of IList<> with actual storage, i.e. it holds an array in the background. In general, an IList<> can be a proxy to something else. In db4o and linq to sql, your IList<> could 'point to a query', i.e. accessing the list will trigger a database operation.

This way, you can perform myList.Skip(600).Take(20); to perform pagination and only in this step will the actual query be executed. A List<> containing a million entries will be huge, while there may be IList<>s that have a huge Count, but don't eat a significant amount of memory - as long as you don't access the elements.

ConvertAll will require each and every object be instantiated so it is a costly operation. Thus, it is better to make the operation explicit and force you to retrieve a specific implementation of the interface. Obviously, conversion requires all objects to be instantiated anyway, so there's no benefit in doing it lazily.

why does C# convertall require 2 parameters

You're using ConvertAll on an Array of cars (Car[]) instead of a List of cars (List) which does indeed require two type parameters1. If cars is a list your code will work.



Related Topics



Leave a reply



Submit