关于list:c#为同一个类实现两个枚举器

c# Implementing two enumerators for the same class

好的,下面是基本代码:

1
2
3
4
5
6
7
8
9
10
11
class foo
{
    String name;
    int property;
}

class bar
{
    private List<foo> a;
    private List<foo> b;
}

我想这样做,以便调用代码可以在任何一个列表上迭代,但我想防止它们被编辑。我已经研究过实现IEnumable接口,但问题是它需要一个"getEnumerable"定义,但我需要两个不同的枚举器。例如,我想说

1
2
foreach(foo in bar.getA())
{ //do stuff }

然后

1
2
foreach(foo in bar.getB())
{ //do stuff }

我是否必须对每个元素进行子类化,并在每个元素上实现IEnumerable接口,然后将这些元素作为属性包含进来?我是否误解了IEnumerable接口?我知道List类有它自己的枚举器,所以我可以做类似的事情

1
2
3
4
5
6
7
8
9
10
11
12
class bar
{
    private List<foo> a;
    private List<foo> b;

    public IEnumerator<foo> getAEnumerator()
    {  return a.GetEnumerator();

    public IEnumerator<foo> getBEnumerator()
    {  return b.GetEnumerator();

}

但我的for循环如下:

1
2
3
4
5
6
bar x = new bar();
IEnumerator<foo> y = x.getAEnumerator();
while (y.moveNext())
{
    foo z = y.Current;
}

所以我失去了"foreach"的可读性。

有没有一种方法可以在这些列表上使用"foreach"而不公开这些列表?我仍在尝试让我的头围绕IEnumerable接口,所以可能我错过了一些明显的东西。


不要暴露List,而是暴露其他东西,比如IReadOnlyList

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class bar
{
    private readonly List<foo> a = new List<foo>();
    private readonly List<foo> b = new List<foo>();

    public IReadOnlyList<foo> A { get; private set; }
    public IReadOnlyList<foo> B { get; private set; }

    public bar()
    {
        A = a.AsReadOnly();
        B = b.AsReadOnly();
    }
}

ab的任何更改将反映在ab中。

还要注意,虽然您可以将List强制转换为IReadOnlyList,但调用代码可以将其强制转换回List。上面的方法返回一个ReadOnlyCollection,它提供了防止回调到可变集合类型的保护。

readonly关键字只确保以后不使用其他内容替换对ab的引用。


1
2
3
4
5
6
7
8
9
class bar
{
    private readonly List<foo> a = new List<foo>();
    private readonly List<foo> b = new List<foo>();

    public IReadOnlyList<foo> A { get {return a.AsReadOnly();}}
    public IReadOnlyList<foo> B { get {return b.AsReadOnly();}}

}

这样,您甚至不需要初始化它,也不需要任何类型的集合