views:

401

answers:

3

Say I have an ArrayList of USBDevice Objects. Each USBDevice has ProductID and VendorID properties (among others). I want to create another ArrayList that is a subset of the first that contains only USBDevice that match a specific VID. What is the shortest way of doing this? I haven't tried this yet but can lambda expressions be used like this...

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

You need a cast. The only thing the compiler knows about ArrayLists is that they contain objects. It doesn't know the types of the objects inside, so you have to tell it.

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

But this seems rather pointless. Why are you using the old ArrayList class and LINQ in the same project? You should try to start using the List<T> class in the System.Collections.Generic namespace instead, then your where expression will work without any casting, just as you want.

Mark Byers
+2  A: 

Yes, you can use Where. But in order to do that you need to cast your ArrayList to USBDevice. This should work:

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

But if you're able to use Linq, why are u using ArrayLists? You should be using generic collections like List instead.

Edit: As Nick pointed out in the comment, using OfType() is recommended if your ArrayList may contain anything other than USBDevice objects.

alexn
If he's using an ArrayList other types may be in the list. Using .OfType<USBDevice>() instead of .Cast<USBDevice>() would avoid exceptions for invalid types.
Nick Gotch
@Nick: Exceptions are good - they let you know that you made an error rather than just carrying on like nothing is wrong.
Mark Byers
@Mark: True but it depends on why he's using an ArrayList. If it's to hold all kinds of "Devices" that don't inherit from a common type this would safely filter out what he's not looking for.
Nick Gotch
+3  A: 

To go along with @Mark Byers' suggestion of using a List<T>, here is some example code:

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();
thedugas
This example works perfect. Thanks!
Jordan S