我有一个ListViewItems数组(ListViewItem[]
),我在每个ListViewItem.Tag中存储一个SalesOrderMaster
对象供以后参考。
我现在有一些代码,通过每个ListViewItem
安全地将.Tag属性转换为SalesOrderMaster对象,然后将该对象添加到SalesOrders的集合中,只有在检查后才能确保订单没有t已存在于该集合中。
比较销售订单的流程非常昂贵,我想将其转换为LINQ表达式,以提高清晰度和性能。 (我也安装了Parallel Extensions to .NET Framework 3.5所以我可以用它来进一步提高LINQ性能)
所以不用多说:这就是我拥有的,然后是我想要的。 (我想要的东西不会编译,所以我知道我做错了什么,但我希望它说明了这一点)
我拥有的:(慢)
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);
}
}
我想要的:(理论)
List<SalesOrderMaster> orders =
(from item in (e.Argument as ListViewItem[]).AsParallel()
select new { ((SalesOrderMaster)item.Tag) }).Distinct();
编辑:我知道演员阵容便宜,我说“比较”,在这种情况下转换为.Contains(订单)操作
编辑:每个人的回答都很棒!我希望我可以标记多个答案,但最后我必须选择一个。
编辑:这就是我最终的结果:
List<SalesOrderMaster> orders =
(from item in (e.Argument as ListViewItem[]) select (SalesOrderMaster) item.Tag).GroupBy(item => item.Number).Select(x => x.First()).ToList();
答案 0 :(得分:18)
我看到没有人明确表示你需要将匿名类型转换为命名类型,所以这里...通过使用“select new { }
”你创建了一个匿名类型,但你不需要。您可以这样编写查询:
List<SalesOrderMaster> orders =
(from item in (e.Argument as ListViewItem[]).AsParallel()
select (SalesOrderMaster)item.Tag)
.Distinct()
.ToList();
请注意,查询选择(SalesOrderMaster)item.Tag
而不是new { }
,因此它不会创建匿名类型。另请注意,我添加了ToList()
,因为您需要List<SalesOrderMaster>
。
这解决了您的匿名类型问题。但是,我同意Mark和Guffa的说法,在这里使用并行查询不是最佳选择。要使用HashSet<SalesOrderMaster>
作为Guffa建议,您可以这样做:
IEnumerable<SalesOrderMaster> query =
from item in (ListViewItem[])e.Argument
select (SalesOrderMaster)item.Tag;
HashSet<SalesOrderMaster> orders = new HashSet<SalesOrderMaster>(query);
(我避免使用var
,因此示例中的返回类型是明确的。)
答案 1 :(得分:3)
该代码中昂贵的部分是调用列表中的Contains
方法。因为它是一个O(n)操作,所以你添加到列表中的对象越多,它就越慢。
只需使用HashSet<SalesOrderMaster>
代替List<SalesOrderMaster>
。 Contains
的{{1}}方法是O(1)操作,因此您的循环将是O(n)操作而不是O(n * n)操作。
答案 2 :(得分:3)
就像Marc Gravell所说,你不应该从不同的线程访问Tag
属性,并且演员阵容非常便宜,所以你有:
var items = (e.Argument as ListViewItem[]).Select(x=>x.Tag)
.OfType<SalesOrderMaster>().ToList();
但是,您希望找到不同的项目 - 您可以尝试使用AsParallel
:
var orders = items.AsParallel().Distinct();