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