tags:

views:

129

answers:

8

Assuming the class

public class Foo 
{
    public List<Bar> Bar = new List<Bar>();
    public string Something;
    public TStatus Status;
}

Bar is a class defined as

public class Bar
{
    public string Code;
    public string Message;
    public TStatus Status;
}

I need to iterate the list Bar but I cant use a foreach because I need to implement IEnumerable I am a bit of a newbie and am having difficulty working out how to implement it, any help appreciated.

+2  A: 

You can do it like this:

var foo = new Foo();
foo.Bar.Add(new Bar {Code = "code1" });
foo.Bar.Add(new Bar {Code = "code2" });

foreach(var b in foo.Bar)
{
     Console.WriteLine(b.Code);
}
klausbyskov
+1  A: 

By the way, if you want these to be properties, make the fields private, so:

private List<Bar> _bar = new List<Bar>();


public IEnumerable<Bar> Bar 
{
    get { return _bar; }
}

Keeps it maintainable in many more contexts.

Lunivore
ehhh? List<> is enumerable..
jgauffin
Yeah, ignore me - I was more focused on the fact that there were public fields there and he wanted them to be properties. The other answers answer the rest of it better.
Lunivore
Note: i'm not the downvoter..
jgauffin
Appreciated. Downvoting less than a minute after I posted, without giving me any chance to reflect and go "Doh" is a bit harsh!
Lunivore
+1  A: 

You should be able to iterate over the members of Bar easily enough using foreach. You don't need to implement IEnumerable here since List<> already does so for you:

var fooInstance = new Foo();
// initialize...
fooInstance.Bar.Add(new Bar {Code = "a" });
fooInstance.Bar.Add(new Bar {Code = "b" });

// iterate over members of Foo.Bar
foreach( var item in fooInstance.Bar )
{
    // access the proeprties of Bar...
    Console.WriteLine( item.Code );
}  
LBushkin
A: 

The following code works for me:

List<Bar> bars = new List<Bar>( );
foreach ( Bar bar in bars ) {
    //Put your code here
}

You should name your instance of List other than Bar to avoid confusion.

PVitt
+1  A: 

You can iterate List<T> as is.

Also - You should be using properties or auto-properties to expose the List<T>, etc. Public fields is bad practice.

Class:

public class Foo 
{
    private List<Bar> _barList;

    public List<Bar> BarList 
    {
        get
        {
            return this._barList ?? (this._barList = new List<Bar>());
        }
    }
}

Iteration:

Foo myFoo = new Foo();

myFoo.BarList.Add(new Bar());
myFoo.BarList.Add(new Bar());

foreach(Bar bar in myFoo.BarList)
{
    //do something with bar
}
KP
+1  A: 

Guess you want to do this:

var enumerator = foo.Bar.GetEnumerator();
while (enumerator.MoveNext())
{
    Console.WriteLine(enumerator.Current);
}
jgauffin
+6  A: 

A couple of things:

1.) As for your actual question, you have two options:

You can iterate over the Bar field (or property, if you change it to a property as outlined below) in your code:

Foo foo = new Foo();

foreach(Bar bar in foo.Bar)
{
    ...
}

Or you can make Foo implement IEnumerable<Bar> (this is more complicated):

public class Foo : IEnumerable<Bar>
{
    .. your existing code goes here

    public IEnumerator<Bar> GetEnumerator()
    {
        return Bar.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return Bar.GetEnumerator();
    }
}

This will allow you to do this:

Foo foo = new Foo();

foreach(Bar bar in foo)
{

}

Personally, I would recommend the first option. It's simpler, and unless Foo really is (rather than it just has) a collection of Bar objects, then it seems more intuitive.

2.) What you have above are not properties, they're public fields. A property has a getter and a setter, and looks something like this:

public class Foo
{
    public string Something
    {
        get { return ...; }
        set { ... = value; }
    }
}

Properties usually operate on a single variable, called a backing store. For the above property, something like this:

public class Foo
{
    private string something;

    public string Something
    {
        get 
        { 
            return something; 
        }
        set  
        { 
            something = value; 
        }
    }
}

Strictly speaking, you could put absolutely any block of code that returns a string in the get block, and you can put anything at all in the set block (including nothing, though that's not a good idea).

Properties allow you to define something that behaves like a field (since you can assign it using the equals sign) but uses the behavior you specify when its value is retrieved or set. However, one of the issues with very simple properties (that just directly get/set a backing variable without any other logic) is that it's a little verbose for what it actually does. That's why C# 3.0 introduced the concept of auto properties, which look like this:

public class Foo
{
    public string Something { get; set; }
}

Here, Something looks a bit like a field, but it's actually a property. The C# compiler recognizes this syntax (replacing the code blocks for both get and set with just a semicolon) and creates a backing variable for you and inserts the code to read from it and write to it.

Adam Robinson
+1  A: 

I'll make a leap here that what you're trying to do is add a property to your Foo class that returns an IEnumerable, or IEnumerable<Bar> and that this property needs to perform some kind of filtering on the list of Bar objects contained in the Foo.Bar field.

EDIT: If this doesn't sound like what you're trying to do, then this answer may not be for you. Please don't let my answer lead you to further confusion.

Here are my assumptions about the problem:

  1. Both Foo and Bar are nested classes within another class, and TStatus is a generic parameter on that containing class.
  2. You want to add a property to Foo that returns a collection of Bar objects that have a Status property equal to the Foo object's Status property. I'm just making a guess here, but I thought that might be why you have a Status property on both Foo and Bar.

Below is a complete implementation that provides a BarsFilteredByStatus property on the Foo class. This uses .NET iterator functionality to provided a filtered collection of Bar objects where Bar.Status equals Foo.Status. If this seems like something along the lines of what you're after, then go ahead, take this code and play around with it.

// an example status enum
enum SomeStatus
{
    Open,
    Closed,
    Funky,
}

// Blarg<TStatus> is just some container class.  This isn't necessary, but it allows TStatus to be a generic parameter rather than a specific type.
class Blarg<TStatus>
{
    public class Bar
    {
        public string Code;
        public string Message;
        public TStatus Status;
    }

    public class Foo
    {
        public List<Bar> Bar = new List<Bar>();
        public string Something;
        public TStatus Status;

        public IEnumerable<Bar> BarsFilteredByStatus
        {
            get
            {
                // return a filtered collection of bars where Bar.Status equals Foo.Status
                foreach (var bar in this.Bar)
                {
                    if (this.Status.Equals(bar.Status))
                        yield return bar;
                }
            }
        }
    }
}

// Code from this point on is a usage example

class Program
{
    static void Main(string[] args)
    {
        // set up some example data
        var bars = new List<Blarg<SomeStatus>.Bar>();
        bars.Add(new Blarg<SomeStatus>.Bar { Code = "123", Status = SomeStatus.Open });
        bars.Add(new Blarg<SomeStatus>.Bar { Code = "234", Status = SomeStatus.Closed });
        bars.Add(new Blarg<SomeStatus>.Bar { Code = "345", Status = SomeStatus.Funky });
        bars.Add(new Blarg<SomeStatus>.Bar { Code = "456", Status = SomeStatus.Open });
        bars.Add(new Blarg<SomeStatus>.Bar { Code = "567", Status = SomeStatus.Funky });

        // create a Foo object
        Blarg<SomeStatus>.Foo foo = new Blarg<SomeStatus>.Foo
        {
            Bar = bars,
            Status = SomeStatus.Open,
        };

        // now iterate over the Foo.BarsFilteredByStatus property
        // This will iterate over all Bar objects contained within Foo.Bar where Bar.Status equals Foo.Status
        foreach (var bar in foo.BarsFilteredByStatus)
        {
            Console.WriteLine(bar.Code);
        }
    }
}
Dr. Wily's Apprentice
This is a lot closer to what I want though I dont need any sorting
Cookie