假设班级
public class Foo
{
public List<Bar> Bar = new List<Bar>();
public string Something;
public TStatus Status;
}
Bar是一个定义为
的类public class Bar
{
public string Code;
public string Message;
public TStatus Status;
}
我需要迭代列表栏但我不能使用foreach因为我需要实现IEnumerable我有点新手并且我很难解决如何实现它,任何帮助表示赞赏。
答案 0 :(得分:11)
有几件事:
1。)至于您的实际问题,您有两种选择:
您可以在代码中迭代Bar
字段(或属性,如果您将其更改为属性,如下所述):
Foo foo = new Foo();
foreach(Bar bar in foo.Bar)
{
...
}
或者您可以Foo
实施IEnumerable<Bar>
(这更复杂):
public class Foo : IEnumerable<Bar>
{
.. your existing code goes here
public IEnumerator<Bar> GetEnumerator()
{
return Bar.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return Bar.GetEnumerator();
}
}
这将允许您这样做:
Foo foo = new Foo();
foreach(Bar bar in foo)
{
}
就个人而言,我会推荐第一个选项。它更简单,除非Foo
真的 (而不仅仅是拥有)Bar
个对象的集合,否则它看起来更直观。< / p>
2。)上面的内容不是属性,而是公共字段。属性有getter和setter,看起来像这样:
public class Foo
{
public string Something
{
get { return ...; }
set { ... = value; }
}
}
属性通常对单个变量进行操作,称为后备存储。对于上述属性,如下所示:
public class Foo
{
private string something;
public string Something
{
get
{
return something;
}
set
{
something = value;
}
}
}
严格地说,您可以放置在get
块中返回字符串的任何代码块,并且您可以在set
块中放置任何内容(包括任何内容,但这不是好主意)。
属性允许您定义行为类似于字段的内容(因为您可以使用等号分配它),但使用您在检索或设置其值时指定的行为。但是,具有非常简单属性的问题之一(只是直接获取/设置后备变量而没有任何其他逻辑)是它实际上做的有点冗长。这就是为什么C#3.0引入了自动属性的概念,如下所示:
public class Foo
{
public string Something { get; set; }
}
在这里,Something
看起来像某个字段,但它实际上是一个属性。 C#编译器识别此语法(仅用分号替换get
和set
的代码块)并为您创建一个后备变量,并插入代码以从中读取并写入。< / p>
答案 1 :(得分:2)
你可以这样做:
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);
}
答案 2 :(得分:2)
顺便说一句,如果您希望这些属性为属性,请将字段设为私有,因此:
private List<Bar> _bar = new List<Bar>();
public IEnumerable<Bar> Bar
{
get { return _bar; }
}
在更多情况下保持可维护性。
答案 3 :(得分:1)
您应该可以使用Bar
轻松地遍历foreach
的成员。您无需在此处实施IEnumerable
,因为List<>
已经为您执行此操作:
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 );
}
答案 4 :(得分:1)
您可以按原样迭代List<T>
。
此外 - 您应该使用属性或自动属性来公开List<T>
等。公共字段是不好的做法。
类别:
public class Foo
{
private List<Bar> _barList;
public List<Bar> BarList
{
get
{
return this._barList ?? (this._barList = new List<Bar>());
}
}
}
迭代:
Foo myFoo = new Foo();
myFoo.BarList.Add(new Bar());
myFoo.BarList.Add(new Bar());
foreach(Bar bar in myFoo.BarList)
{
//do something with bar
}
答案 5 :(得分:1)
猜猜你想这样做:
var enumerator = foo.Bar.GetEnumerator();
while (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
}
答案 6 :(得分:1)
我会在这里做一个飞跃,你要做的是在你的Foo
类中添加一个返回IEnumerable
或IEnumerable<Bar>
并且此属性需要的属性对Bar
字段中包含的Foo.Bar
个对象列表执行某种过滤。
编辑:如果这听起来不像你想要做的那样,那么这个答案可能不适合你。请不要让我的回答让你进一步混淆。
以下是我对此问题的假设:
Foo
和Bar
都是另一个类中的嵌套类,而TStatus
是包含该类的通用参数。Foo
添加一个属性,该属性返回Bar
个对象的集合,这些对象的Status
属性等于Foo
对象的Status
属性。我在这里猜测,但我认为这可能就是Status
和Foo
上Bar
属性的原因。以下是一个完整的实现,它在BarsFilteredByStatus
类上提供Foo
属性。这使用.NET iterator functionality提供了Bar
对象的过滤集合,其中Bar.Status
等于Foo.Status
。如果这看起来像你所追求的那样,那就继续吧,拿这个代码来玩吧。
// 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);
}
}
}
答案 7 :(得分:0)
以下代码适用于我:
List<Bar> bars = new List<Bar>( );
foreach ( Bar bar in bars ) {
//Put your code here
}
您应该将List的实例命名为Bar以外的其他实例以避免混淆。