过滤数组列表内容的最佳方法是什么?

问题描述:

假设我有一个USBDevice对象的ArrayList。每个USB设备都有ProductID和VendorID属性(等等)。我想创建另一个ArrayList,它是第一个仅包含与特定VID匹配的USBDevice的子集。做这件事的最简单方法是什么?我还没有试过这个,但可以使用lambda表达式,像这样...过滤数组列表内容的最佳方法是什么?

ArrayList CompleteList = new ArrayList(); 
... 
// Fill CompleteList with all attached devices.... 
... 
ArrayList SubSetList = CompleteList.Where(d => d.VID == "10C4") 

你需要一个演员。编译器知道的关于ArrayLists的唯一事情是它们包含对象。它不知道里面的物体的类型,所以你必须告诉它。

ArrayList subSetList = new ArrayList(CompleteList.Cast<USBDevice>() 
               .Where(d => d.VID == "10C4") 
               .ToList()); 

但这似乎没有意义。为什么在同一个项目中使用旧的ArrayList类和LINQ?您应该尝试开始在System.Collections.Generic名称空间中使用List<T>类,然后您的where表达式将在没有任何投射的情况下工作,就像您想的那样。

是的,你可以使用Where。但为了做到这一点,您需要将您的ArrayList强制转换为USBDevice。这应该工作:

var subset = CompleteList.Cast<USBDevice>().Where(x =>d.VID = "10C4"); 

但是,如果你能够使用Linq,为什么你使用ArrayLists?您应该使用像List这样的通用集合。

编辑:正如尼克在评论中指出的那样,如果您的ArrayList可能包含USBDevice对象以外的其他任何东西,建议使用OfType()。

+2

如果他使用一个ArrayList其他类型的可在列表中。使用.OfType ()而不是.Cast ()将避免无效类型的例外。 – 2010-02-23 15:50:24

+1

@Nick:例外情况很好 - 他们让你知道你犯了一个错误,而不是像没有任何错误一样继续。 – 2010-02-23 15:53:23

+0

@Mark:真的,但这取决于他为什么使用ArrayList。如果要保存各种不能从普通类型继承的“设备”,这将安全地过滤掉他不需要的东西。 – 2010-02-23 16:08:06

要随着使用列表<牛逼>的@马克拜尔斯的建议,走,这里是一些示例代码:

List<USBDevice> CompleteList = new List<USBDevice>(); 
CompleteList.Add(new USBDevice(){VID = "10C4", Other = "x"}); 
CompleteList.Add(new USBDevice() { VID = "10C4", Other = "x" }); 

//..Fill CompleteList with all attached devices.... 

List<USBDevice> SubSetList = new List<USBDevice>(); 
SubSetList = CompleteList.Where(d => d.VID.Equals("10C4")).ToList(); 
+0

这个例子很完美。谢谢! – PICyourBrain 2010-02-23 19:03:26