tags:

views:

46

answers:

2

Suppose I have a class

public class Foo
{
    public Bar Bar { get; set; }
}

Then I have another class

public class Gloop
{
    public List<Foo> Foos { get; set; }
}

What's the easiest way to get a List<Bar> of Foo.Bars?

I'm using C# 4.0 and can use Linq if that is the best choice.

UPDATE:

Just for a little dose of reality, the reason for this is that I have a Windows Service class that contains an inner ServiceBase derived class as a property. So I end up with code like this:

public class Service
{
    public ServiceBase InnerService { get; set; }
}

public class ServiceHost
{
    private List<Service> services = new List<Service>();
    static void Main()
    {
         // code to add services to the list
         ServiceBase.Run(services.Select(service => service.InnerService).ToArray());
    }
}
+2  A: 

This one's simple, if I've understood you rightly:

List<Foo> foos = gloop.Foos; // Or wherever you're getting it from
List<Bar> bars = foos.Select(foo => foo.Bar)
                     .ToList();

If you only need an IEnumerable<Bar> you can just use Select without the call to ToList. Of course you don't need the foos local variable if you don't want it - you can just have a single statement. I've only separated them out in case you've got an existing List<Foo> or Foo[] (you mention arrays in your subject line).

Jon Skeet
What's more efficient, the Select with lambda, or something like (from b in gloop.Foos select b.Bar).ToList()
Mystere Man
@Mystere Man: They end up as the same IL, but I don't see any reason for using a query expression when you're just doing a simple projection. It's extra clutter.
Jon Skeet
Since he mentioned Linq, the Linq equivalent for the second statement should be:List<Bar> bars = (from f in foos.Bar select f).ToList();
mynameiscoffey
Good point Jon, as usual, you're the voice of reason and wisdom ;)
Mystere Man
@mynameiscoffey: Why? LINQ doesn't necessitate the use of query expressions IMO. We're still using LINQ to Objects, but taking the simplest syntax for the situation, IMO. Not to mention the fact that your query wouldn't work as written ;)
Jon Skeet
Ran it through LinqPad, both the lambda and linq compile to the exact same IL
mynameiscoffey
@mynameiscoffee: Um, not the query expression your comment shows, which is trying to use `foos.Bar` as a source, and just selecting `f`. If you use the query expression that Mystere Man specified *then* it would give the same IL. But again, LINQ != query expressions. Both syntax forms are using LINQ.
Jon Skeet
I was talking in response to your comment to Mystere Man, you guys type faster than me ;). I was genuinely curious (as it sounded like Mystere Man was as well). Linq is new grounds to me, forgive my ignorance with naming and my bad query expression.
mynameiscoffey
@mynameiscoffey: No problem :) Basically the compiler does a translation from the query expression form to code which doesn't use query expressions before it generates the IL. See section 7.16 of the C# 4 spec.
Jon Skeet
I wasn't aware that Linqpad showed you the IL generated.. i really need to start using that more...
Mystere Man
Wow, just ran that through Linqpad and you're absolutely right, identical code for both. You taught me two things today Jon.. a twofer
Mystere Man
+1  A: 

var bars = gloop.Foos.Select(foo => foo.Bar);

carlmon
As stated in another answer, this only returns `IEnumerable<Bar>`. Use `ToList()` if you need it as `List<Bar>`.
carlmon
did you forget to add the "ToList()"? or is that the return type of the Select call?
VoodooChild
Yes, I forgot the `ToList()` in my initial (quick) answer. IList adds some additional functionality to IEnumerable, like insert/delete which may be inappropriate given the source.
carlmon