实现集合的简单方法?

时间:2011-05-26 08:58:32

标签: c# .net ienumerable yield ienumerator

我正在开发一个集合类,它应该实现IEnumerator和IEnumerable。

在我的第一种方法中,我直接实施了它们。现在我已经发现了yield关键字,并且我已经能够简化所有内容,将IEnumerator / IEnumerable接口替换为readonly属性,使用yield返回循环中的IEnumerable。

我的问题:是否有可能以这样的方式使用yield,我可以迭代类本身,而无需实现IEnumerable / IEnumerator?

即,我希望有一个类似于框架集合的功能:

List<int> myList = new List<int>();
foreach (int i in myList)
{
    ...
}

这有可能吗?

更新:似乎我的问题措辞严厉。我不介意实现IEnumerator或IEnumerable;我只是认为唯一的方法是使用旧的Current / MoveNext / Reset方法。

2 个答案:

答案 0 :(得分:9)

您不会 实施IEnumerable<T>IEnumerable以使foreach工作 - 但这样做是个好主意。这很容易做到:

public class Foo : IEnumerable<Bar>
{
    public IEnumerator<Bar> GetEnumerator()
    {
        // Use yield return here, or 
        // just return Values.GetEnumerator()
    }

    // Explicit interface implementation for non-generic
    // interface; delegates to generic implementation.
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

实施IEnumerable<T>的替代方案只会调用您的Values属性,但仍提供GetEnumerator()方法:

public class Foo
{
    public IEnumerator<Bar> GetEnumerator()
    {
        // Use yield return here, or 
        // just return Values.GetEnumerator()
    }
]

虽然这样可行,但这意味着您将无法将集合传递给期望IEnumerable<T>的任何内容,例如LINQ to Objects。

一个鲜为人知的事实是,foreach适用于支持GetEnumerator()方法的任何类型,该方法返回具有适当MoveNext()Current成员的类型。这实际上是允许在泛型之前使用强类型集合,其中迭代集合不会包含值类型等。现在真的没有调用它,IMO。

答案 1 :(得分:1)

你可以这样做,但为什么呢? IEnumerator已经很简单了。

Interface MyEnumerator<T>
{
    public T GetNext();
}

public static class MyEnumeratorExtender
{
    public static void MyForeach<T>(this MyEnumerator<T> enumerator,
        Action<T> action)
    {
        T item = enumerator.GetNext();
        while (item != null)
        {
            action.Invoke(item);
            item = enumerator.GetNext();
        }
    }
}

我宁愿拥有in关键字,我也不想重写linq。