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.
Asked
Active
Viewed 306 times
4

Jack
- 7,433
- 22
- 63
- 107
-
^ Konstantin, it is - however its a real good question. @ Jack - This is better for "Code Review" – Brandt Solovij Dec 06 '12 at 06:33
-
Besides your code does not reflect the situation when `s.HasValue == false`... – horgh Dec 06 '12 at 06:33
-
Are you guaranteed that all objects will have a value? – Maurice Reeves Dec 06 '12 at 06:34
-
@ Maurice - hes not. CODE REVIEW TOPIC NOT STACK !!! – Brandt Solovij Dec 06 '12 at 06:34
-
@Maurico: Yes. Next question from Konstanin would be so why use List
. Answer is I have to because it is returned from 3rd party lib. – Jack Dec 06 '12 at 06:35 -
@Jack so you should consider that it may contain `null`, shouldn't you? – horgh Dec 06 '12 at 06:37
-
no, it doesn't. It never returns null. Don't know why the lib developer used List
– Jack Dec 06 '12 at 06:37
2 Answers
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
-
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,835
- 6
- 32
- 63
-
2+1 but what about efficiency? You cannot do better than O(n) with cast anyway, I think. And you have to do `.Where(x => x.HasValue)` to check nulls – Roman Pekar Dec 06 '12 at 06:38
-
2
-
1Also this is slower than the original code by a factor of 3 for 200000 items. – Mike Zboray Dec 06 '12 at 06:39
-
@mikez: Really? It looks better than original. I assume built in extension method would be faster. I will test this. – Jack Dec 06 '12 at 06:41
-
@RomanPekar & mike you are right.but i have suggested the way to deceive some one it is efficient :) – Behnam Esmaili Dec 06 '12 at 06:41
-
-
@Jack i was just kidding.you'r code will be even more efficient if you put it inside try - catch.if you don't believe me check this : http://stackoverflow.com/questions/8928403/try-catch-speeding-up-my-code\ – Behnam Esmaili Dec 06 '12 at 06:43