实现集合的简单方法?

发布于 2024-11-10 06:31:24 字数 509 浏览 4 评论 0原文

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

在我的第一种方法中,我直接实现了它们。现在我发现了yield关键字,并且我已经能够简化一切,用只读属性Values替换IEnumerator/IEnumerable接口,该只读属性值使用yield在循环中返回IEnumerable。

我的问题:是否可以使用 Yield 来迭代类本身,而无需实现 IEnumerable/IEnumerator?

即,我想要具有类似于框架集合的功能:

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

这可能吗?

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

I am developing a collection class, which should implement IEnumerator and IEnumerable.

In my first approach, I implemented them directly. Now I have discovered the yield keyword, and I have been able to simplify everything a whole lot substituting the IEnumerator/IEnumerable interfaces with a readonly property Values that uses yield to return an IEnumerable in a loop.

My question: is it possible to use yield in such a way that I could iterate over the class itself, without implementing IEnumerable/IEnumerator?

I.e., I want to have a functionality similar to the framework collections:

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

Is this possible at all?

Update: It seems that my question was badly worded. I don't mind implementing IEnumerator or IEnumerable; I just thought the only way to do it was with the old Current/MoveNext/Reset methods.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

随风而去 2024-11-17 06:31:24

您不必必须实现 IEnumerableIEnumerable 来让 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 的替代方法只是调用您的 Values 属性,但仍然提供 < code>GetEnumerator() 方法:

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

虽然这可行,但这意味着您将无法将集合传递给任何需要 IEnumerable 的对象,例如 LINQ to对象。

一个鲜为人知的事实是,foreach 可以与任何支持 GetEnumerator() 方法的类型一起使用,该方法返回具有适当 MoveNext() 的类型,并且当前成员。这实际上是为了在泛型之前允许强类型集合,其中迭代集合不会框出值类型等。在我看来,现在确实没有必要这样做。

You won't have to implement IEnumerable<T> or IEnumerable to get foreach to work - but it would be a good idea to do so. It's very easy to do:

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();
    }
}

The alternative which doesn't implement IEnumerable<T> would just call your Values property, but still providing a GetEnumerator() method:

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

While this will work, it means you won't be able to pass your collection to anything expecting an IEnumerable<T>, such as LINQ to Objects.

It's a little-known fact that foreach will work with any type supporting a GetEnumerator() method which returns a type with appropriate MoveNext() and Current members. This was really to allow strongly-typed collections before generics, where iterating over the collection wouldn't box value types etc. There's really no call for it now, IMO.

与之呼应 2024-11-17 06:31:24

你可以做这样的事情,但为什么呢? 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。

You could do somthing like this, but why? IEnumerator is already simple.

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();
        }
    }
}

I'd rather have the in keyword and I wouldn't want to rewrite linq.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文