4

At the moment I use List<int> ints = tuple.Item2.Select(s => s.Value).ToList() but this looks inefficient when tuple.Item2 has 1000's of items. Any better way to achieve this? except using a for loop.

Jack
  • 7,173
  • 18
  • 59
  • 105

2 Answers2

7

The built-in way to convert each element in one List<T1> and store the result in another List<T2> is List<T1>.ConvertAll.

List<int> ints = tuple.Item2.ConvertAll(s => s.Value);

Unlike .Select(...).ToList() or .Cast(...).ToList(), this method knows the list size in advance, and prevents unnecessary reallocations that .ToList() cannot avoid.

For this to work, tuple.Item2 must really be a List<int?>. It's not an extension method, it cannot work on the generic IEnumerable<int?> interface.

  • It could be that `s => s.GetValueOrDefault()` is faster than just `s => s.Value`. This may seem surprising, but the reason is that `.GetValueOrDefault()` always and unconditionally exposes the backing field (`value`), while the `.Value` property first checks the Boolean field (`hasValue`) to see if it is true or false, and only then exposes that backing field (or throws if `hasValue` was false). The `Nullable<>` struct ensures that the backing field always has its default value in the case where we are modeling a "null", so that is why the behavior of `.GetValueOrDefault()` is safe. – Jeppe Stig Nielsen Apr 16 '22 at 08:39
  • You can also write it as `s => s ?? 0`. – Jeppe Stig Nielsen Apr 16 '22 at 08:46
2

you can simply use Linq Cast<> to achieve this .

List<int> ints = tuple.Item2.Cast<int>();

but if an element cannot be cast to type TResult, this method will throw an exception.you have to consider catching exception.

Behnam Esmaili
  • 5,715
  • 6
  • 30
  • 60