2010-10-18 75 views
3

IEnumerable的假設類落實財產

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

酒吧是定義爲

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

我需要遍歷列表欄,但因爲我需要實現IEnumerable我我不能使用foreach類有點新手,我很難制定如何實施它,任何幫助表示讚賞。

+3

'List '* already * implement'IEnumerable'。你爲什麼認爲你需要自己實現它? – 2010-10-18 17:22:53

+0

您是否在討論迭代「Bar」列表?或者你在說什麼迭代每個「酒吧」的成員?你已經迭代了一個List 對象。 – 2010-10-18 17:23:34

+1

你能發佈不能編譯的代碼嗎?下面有很多答案,但不知何故,我不認爲這些描述了你的問題。 – 2010-10-18 17:23:43

回答

11

幾件事情:

1)作爲爲y我們的實際問題,你有兩個選擇:

您可以遍歷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對象的集合,那麼它似乎更直觀。

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#編譯器識別此語法(用分號替代getset的代碼塊),併爲您創建一個支持變量,並插入代碼以從中讀取並寫入該代碼。

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

順便說一句,如果你想這是性質,使字段私有的,所以:

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


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

保持它維護的更多上下文。

+0

ehhh?列表<>是可枚舉的。 – jgauffin 2010-10-18 17:26:47

+0

是的,不理我 - 我更關注於那裏有公共領域,他希望他們是屬性。其他答案更好地回答了其餘部分。 – Lunivore 2010-10-18 17:29:05

+0

注意:我不是downvoter .. – jgauffin 2010-10-18 17:32:07

1

您應該可以使用foreach輕鬆地遍歷Bar的成員。你並不需要在這裏實現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); 
} 
0

下面的代碼對我的作品:

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

您應該爲您比其他酒吧名單的一個實例來避免混亂。

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 
} 
1

猜你想這樣做:

var enumerator = foo.Bar.GetEnumerator(); 
while (enumerator.MoveNext()) 
{ 
    Console.WriteLine(enumerator.Current); 
} 
1

我將做一個飛躍,在這裏,你正在試圖做的是一個屬性添加到您的Foo類返回IEnumerable,或IEnumerable<Bar>而且這種屬性需要的Bar名單上執行某種過濾包含在Foo.Bar字段中的對象。

編輯:如果這聽起來不像你想要做的,那麼這個答案可能不適合你。請不要讓我的回答讓你更加困惑。

下面是我對問題的假設:

  1. 兩個FooBar是另一類內嵌套類,TStatus是含有類泛型參數。
  2. 要將屬性添加到Foo,該屬性將返回一個具有Status屬性等於Foo對象的Status屬性的Bar對象的集合。我只是在這裏猜測,但我認爲這可能是爲什麼你在FooBar上都有Status屬性。

下面是在Foo類中提供BarsFilteredByStatus屬性的完整實現。這使用.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); 
     } 
    } 
} 
+0

雖然我不需要任何排序,但這與我想要的更接近 – Cookie 2010-10-19 09:03:11