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.
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.
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:
Foo
and Bar
are nested classes within another class, and TStatus
is a generic parameter on that containing class.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);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With