I'm looking at some code that takes an IEnumerable<T>
and converts it to a List<T>
so it can use List<T>.Find(predicate)
:
var myEnumerable = ...;
var myList = new List<T>(myEnumerable);
var match = myList.Find(value => value.Aaa == aaa && value.Bbb == bbb);
Is there a way to rewrite this using the LINQ extension methods that has the same effect, but without building an extra List<T>
as an intermediate step?
The FirstOrDefault(source, predicate)
extension method looks like a good candidate, but trying to figure out if it's exactly equivalent to Find
is making my head hurt.
You want to search an object in object list. This will help you in getting the first or default value in your Linq List search. Show activity on this post. You can use FirstOfDefault with the Where LINQ extension to get a MessageAction class from the IEnumerable.
Linq Except is the C# equivalent of using “Where X Not In” in SQL. There are all sorts of reasons you might want the values from one list that aren’t in another, for instance:
I wasn’t sure, so I tried it, and yes, these Linq methods do preserve the order of the items in the Lists: Hopefully this has given you a good introduction to performing set based operations in C# with Linq. In particular using Except to find the items in one list that aren’t in another.
which are the equivalents of: LINQ’s Take and Skip methods are very useful for paging data, or limiting the amount you process, and TakeWhile and SkipWhile come in handy from time to time as well (TakeWhile can be a good way of checking for user cancellation). Take and Skip can be implemented using the itertools islice function.
Just for reference, here is a table of some old .NET 2 style List<>
instance methods, and their equivalent extension methods in Linq:
METHOD IN List<> METHOD IN Linq
------------------------------------------------------------------------------------------
list.Contains(item) query.Contains(item)
list.Exists(x => x.IsInteresting()) query.Any(x => x.IsInteresting())
list.TrueForAll(x => x.IsInteresting()) query.All(x => x.IsInteresting())
list.Find(x => x.IsInteresting()) query.FirstOrDefault(x => x.IsInteresting())
list.FindLast(x => x.IsInteresting()) query.LastOrDefault(x => x.IsInteresting())
list.FindAll(x => x.IsInteresting()) query.Where(x => x.IsInteresting())
list.ConvertAll(x => x.ProjectToSomething()) query.Select(x => x.ProjectToSomething())
Of course some of them are not entirely equivalent. In particular Linq's Where
and Select
use deferred execution, while FindAll
and ConvertAll
of List<>
will execute immediately and return a reference to a new List<>
instance.
FindLast
will often be faster than LastOrDefault
because FindLast
actually searches starting from the end of the List<>
. On the other hand LastOrDefault(predicate)
always runs through the entire sequence (starting from the first item), and only then returns the most "recent" match.
The LINQ equivelent would be to use FirstOrDefault:
var match = myEnumerable.FirstOrDefault(value => value.Aaa == aaa && value.Bbb == bbb);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With