10

假设以下类:

public class MyEnum: IEnumerator
{
    private List<SomeObject> _myList = new List<SomeObject>();
...
}

有必要在 MyEnum 中实现 IEnumerator 方法。但是是否可以将 IEnumerator 的实现直接“委托”或重定向到 _myList 而无需实现 IEnumerator 方法?

4

7 回答 7

8

方法一: 继续使用封装,将调用转发到List实现。

class SomeObject
{
}

class MyEnum : IEnumerable<SomeObject>
{
    private List<SomeObject> _myList = new List<SomeObject>();

    public void Add(SomeObject o)
    {
        _myList.Add(o);
    }

    public IEnumerator<SomeObject> GetEnumerator()
    {
        return _myList.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyEnum a = new MyEnum();
        a.Add(new SomeObject());

        foreach (SomeObject o in a)
        {
            Console.WriteLine(o.GetType().ToString());
        }

        Console.ReadLine();
    }
}

方法 2: 从 List 实现继承您可以免费获得该行为。

class SomeObject
{
}

class MyEnum : List<SomeObject>
{
}

class Program
{
    static void Main(string[] args)
    {
        MyEnum a = new MyEnum();
        a.Add(new SomeObject());

        foreach (SomeObject o in a)
        {
            Console.WriteLine(o.GetType().ToString());
        }

        Console.ReadLine();
    }
}

方法 1允许更好的沙盒,因为在没有 MyEnum 知识的情况下不会在 List 中调用任何方法。为了最少的努力,方法 2是首选。

于 2008-09-24T09:27:31.920 回答
1

你可以这样做:

public class MyEnum : IEnumerator {
    private List<SomeObject> _myList = new List<SomeObject>();
    public IEnumerator GetEnumerator() { return this._myList.GetEnumerator(); }
}

原因很简单。您的类可以包含多个作为集合的字段,因此编译器/环境无法知道应该使用哪个字段来实现“IEnumerator”。

EIDT:我同意@pb - 你应该实现 IEnumerator<SomeObject> 接口。

于 2008-09-24T09:25:54.017 回答
1

除了使用 pb 的方法之外,这是不可能的,原因很简单:接口方法需要传递一个this指针作为第一个参数。当你调用GetEnumerator你的对象时,这个指针就是你的对象。但是,为了使调用在嵌套列表上工作,指针必须是对该列表的引用,而不是您的类。

因此,您必须明确地将方法委托给另一个对象。

(顺便说一句,另一个回复中的建议是正确的:使用IEnumerator<T>而不是 IEnumerable!)

于 2008-09-24T09:27:38.893 回答
0

如果要以调用者无法修改集合的方式返回集合,则可能需要将 List 包装到 ReadOnlyCollection<> 并返回 ReadOnlyCollection<> 的 IEnumerable<>。

这样您就可以确保您的收藏不会被更改。

于 2008-09-24T09:27:26.117 回答
-1

除非你从 List<T> 派生。

public class MyEnum : List<SomeObject>, IEnumerable<SomeObject>{}
于 2008-09-24T09:18:24.987 回答
-1

谢谢大家的意见和解释。最终,我将您对以下问题的一些答案结合在一起:

    class MyEnum : IEnumerable<SomeObject>
{
    private List<SomeObject> _myList = new List<SomeObject>();
    public IEnumerator<SomeObject> GetEnumerator()
    {
        // Create a read-only copy of the list.
        ReadOnlyCollection<CustomDevice> items = new ReadOnlyCollection<CustomDevice>(_myList);
        return items.GetEnumerator();
    }
}

该解决方案是为了确保调用代码无法修改列表,并且每个枚举器在各个方面都独立于其他枚举器(例如,使用排序)。再次感谢。

于 2008-09-24T09:54:23.463 回答
-1

请注意,多亏了鸭子类型,您可以foreach在任何具有GetEnumerator方法的对象上使用 - 对象类型不需要实际实现IEnumerable

所以如果你这样做:

class SomeObject
{
}

 class MyEnum
 {
    private List<SomeObject> _myList = new List<SomeObject>();

    public IEnumerator<SomeObject> GetEnumerator()
    {
        return _myList.GetEnumerator();
    }
 }

然后这工作得很好:

MyEnum objects = new MyEnum();
// ... add some objects
foreach (SomeObject obj in objects)
{
    Console.WriteLine(obj.ToString());
}
于 2017-06-07T20:42:08.063 回答