I have an array of ListViewItems ( ListViewItem[] ), where I store a SalesOrderMaster object in each ListViewItem.Tag for later reference.
I have some code that right now, goes through each ListViewItem safely casts the .Tag property into a SalesOrderMaster object, then adds that object to a collection of SalesOrders, only after checking to make sure the order doesn’t already exist in that collection.
The process to compare sales orders is expensive, and I would like to convert this to a LINQ expression for clarity and performance. ( I also have the Parallel Extensions to .NET Framework 3.5 installed so I can use that to further improve LINQ performance)
So without further ado: This is what I have, and then what I want. ( what I want won’t compile, so I know I am doing something wrong, but I hope it illustrates the point )
What I have: ( Slow )
foreach (ListViewItem item in e.Argument as ListViewItem[])
{
SalesOrderMaster order = item.Tag as SalesOrderMaster;
if ( order == null )
{
return;
}
if (!All_SalesOrders.Contains(order))
{
All_SalesOrders.Add(order);
}
}
What I want: ( Theory )
List<SalesOrderMaster> orders =
(from item in (e.Argument as ListViewItem[]).AsParallel()
select new { ((SalesOrderMaster)item.Tag) }).Distinct();
EDIT: I know the cast is cheap, I said the “Compare”, which in this case translates to the .Contains(order) operation
EDIT: Everyone’s answer was awesome! I wish I could mark more than one answer, but in the end I have to pick one.
EDIT : This is what I ended up with:
List<SalesOrderMaster> orders =
(from item in (e.Argument as ListViewItem[]) select (SalesOrderMaster) item.Tag).GroupBy(item => item.Number).Select(x => x.First()).ToList();
I see nobody has addressed your need to convert an anonymous type to a named type explicitly, so here goes… By using “
select new { }” you are creating an anonymous type, but you don’t need to. You can write your query like this:Notice that the query selects
(SalesOrderMaster)item.Tagwithoutnew { }, so it doesn’t create an anonymous type. Also note I addedToList()since you want aList<SalesOrderMaster>.This solves your anonymous type problem. However, I agree with Mark and Guffa that using a parallel query here isn’t you best option. To use
HashSet<SalesOrderMaster>as Guffa suggested, you can do this:(I avoided using
varso the returned types are clear in the examples.)