I have an array of ListViewItems ( ListViewItem[]
), where I store a SalesOrderMaster
object in each ListViewItem.Tag for later reference.
I ha
Like Marc Gravell said, you shouldn't access the Tag
property from different threads, and the cast is quite cheap, so you have:
var items = (e.Argument as ListViewItem[]).Select(x=>x.Tag)
.OfType<SalesOrderMaster>().ToList();
but then, you want to find distinct items - here you can try using AsParallel
:
var orders = items.AsParallel().Distinct();
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:
List<SalesOrderMaster> orders =
(from item in (e.Argument as ListViewItem[]).AsParallel()
select (SalesOrderMaster)item.Tag)
.Distinct()
.ToList();
Notice that the query selects (SalesOrderMaster)item.Tag
without new { }
, so it doesn't create an anonymous type. Also note I added ToList()
since you want a List<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:
IEnumerable<SalesOrderMaster> query =
from item in (ListViewItem[])e.Argument
select (SalesOrderMaster)item.Tag;
HashSet<SalesOrderMaster> orders = new HashSet<SalesOrderMaster>(query);
(I avoided using var
so the returned types are clear in the examples.)
The part in that code that is expensive is calling the Contains
method on the list. As it's an O(n) operation it gets slower the more objects you add to the list.
Just use a HashSet<SalesOrderMaster>
for the objects instead of a List<SalesOrderMaster>
. The Contains
method of the HashSet
is an O(1) operation, so your loop will be an O(n) operation instead of an O(n*n) operation.