为什么在这个例子中(来自msdn),在GetEnumerator方法中,new PeopleEnum返回IEnumerator?

发布于 2024-08-28 14:49:12 字数 1578 浏览 4 评论 0原文

为什么在 MSDN 的这个示例中,在 GetEnumerator 方法中,PeopleEnum 返回 IEnumerator

public class Person
{
    public Person(string fName, string lName)
    {
        this.firstName = fName;
        this.lastName = lName;
    }

    public string firstName;
    public string lastName;
}

public class People : IEnumerable
{
    private Person[] _people;
    public People(Person[] pArray)
    {
        _people = new Person[pArray.Length];

        for (int i = 0; i < pArray.Length; i++)
        {
            _people[i] = pArray[i];
        }
    }
   //why??? 
   IEnumerator IEnumerable.GetEnumerator()
   {
       return (IEnumerator) GetEnumerator();
   }

   public PeopleEnum GetEnumerator()
   {
       return new PeopleEnum(_people);
   }
}

public class PeopleEnum : IEnumerator
{
    public Person[] _people;

// Enumerators are positioned before the first element
// until the first MoveNext() call.
int position = -1;

public PeopleEnum(Person[] list)
{
    _people = list;
}

public bool MoveNext()
{
    position++;
    return (position < _people.Length);
}

public void Reset()
{
    position = -1;
}

object IEnumerator.Current
{
    get
    {
        return Current;
    }
}

public Person Current
{
    get
    {
        try
        {
            return _people[position];
        }
        catch (IndexOutOfRangeException)
        {
            throw new InvalidOperationException();
        }
    }
}

更新: 顺便说一句,如果Array数据类型实现了ICloneable接口,为什么msdn通过编写for循环将pArray复制到_people?

Why in this example from MSDN, in GetEnumerator method, PeopleEnum returns IEnumerator?

public class Person
{
    public Person(string fName, string lName)
    {
        this.firstName = fName;
        this.lastName = lName;
    }

    public string firstName;
    public string lastName;
}

public class People : IEnumerable
{
    private Person[] _people;
    public People(Person[] pArray)
    {
        _people = new Person[pArray.Length];

        for (int i = 0; i < pArray.Length; i++)
        {
            _people[i] = pArray[i];
        }
    }
   //why??? 
   IEnumerator IEnumerable.GetEnumerator()
   {
       return (IEnumerator) GetEnumerator();
   }

   public PeopleEnum GetEnumerator()
   {
       return new PeopleEnum(_people);
   }
}

public class PeopleEnum : IEnumerator
{
    public Person[] _people;

// Enumerators are positioned before the first element
// until the first MoveNext() call.
int position = -1;

public PeopleEnum(Person[] list)
{
    _people = list;
}

public bool MoveNext()
{
    position++;
    return (position < _people.Length);
}

public void Reset()
{
    position = -1;
}

object IEnumerator.Current
{
    get
    {
        return Current;
    }
}

public Person Current
{
    get
    {
        try
        {
            return _people[position];
        }
        catch (IndexOutOfRangeException)
        {
            throw new InvalidOperationException();
        }
    }
}

UPDATE:
BTW, if Array data type implements ICloneable interface, why msdn has copied pArray to _people by writing a for loop?

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

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

发布评论

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

评论(2

单身狗的梦 2024-09-04 14:49:24

实现 IEnumerable 的类型需要一个名为 GetEnumerator 的方法,该方法返回 IEnumerator。在该示例中(从 C# 2.0 开始已经过时),有一个实现 IEnumerator 的枚举器类 PeopleEnum。这是 C# foreach 语句在内部使用的内容。

更新的示例如下所示。请注意,既然 C# 支持迭代器,就不再需要 PeopleEnum 类。实际上,编译器会为您完成所有繁重的工作。

public class People : IEnumerable
{
    private Person[] _people;
    public People(Person[] pArray)
    {
        _people = new Person[pArray.Length];

        for (int i = 0; i < pArray.Length; i++)
        {
            _people[i] = pArray[i];
        }
    }

   IEnumerator IEnumerable.GetEnumerator()
   {
       for (int i=0; i < _people.Length; i++) {
           yield return _people[i];
       }
   }
}

Types implementing IEnumerable require a method called GetEnumerator that returns an IEnumerator. In that example (which is pretty obsolete as of C# 2.0) there is an enumerator class PeopleEnum that implements IEnumerator. It's what's used internally by the C# foreach statement.

A more up to date example would look more like the following. Note there's no longer a need for a PeopleEnum class now that C# supports iterators. Effectively the compiler does all the heavy lifting for you.

public class People : IEnumerable
{
    private Person[] _people;
    public People(Person[] pArray)
    {
        _people = new Person[pArray.Length];

        for (int i = 0; i < pArray.Length; i++)
        {
            _people[i] = pArray[i];
        }
    }

   IEnumerator IEnumerable.GetEnumerator()
   {
       for (int i=0; i < _people.Length; i++) {
           yield return _people[i];
       }
   }
}
请你别敷衍 2024-09-04 14:49:22

它需要准确返回IEnumerator才能正确实现IEnumerable接口。它使用“显式接口实现”来执行此操作,因此在 public API 上您会看到 PeopleEnum,但 IEnumerable 仍然很高兴

但实际上在 C# 2.0 或更高版本中,您很少会以这种方式编写枚举器;您将使用迭代器块(yield return)。请参阅深入了解 C# 第 6 章(免费章节!)。

作为信息,PeopleEnum 存在的原因根本是因为它看起来像 .NET 1.1 示例,这是创建类型化枚举器的唯一方法。在 .NET 2.0 及更高版本中,有 IEnumerable / IEnumerator,它具有类型化(通过泛型).Current

在 .NET 2.0 / C# 2.0 (或更高版本)中,我会简单地:

public class People : IEnumerable<Person> {
    /* snip */
    public IEnumerator<Person> GetEnumerator() {
        return ((IEnumerable<Person>)_people).GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator() { return _people.GetEnumerator();}
}

It needs to return exactly IEnumerator to properly implement the IEnumerable interface. It is doing this using an "explicit interface implementation", so on the public API you see PeopleEnum, but IEnumerable is still happy

But in reality you would very rarely write an enumerator this way in C# 2.0 or above; you'd use an iterator block (yield return). See C# in Depth chapter 6 (free chapter!).

For info, the reason that PeopleEnum exists at all here is that this looks like a .NET 1.1 sample, where that is the only way to create a typed enumerator. In .NET 2.0 and above there is IEnumerable<T> / IEnumerator<T>, which has a typed (via generics) .Current.

In .NET 2.0 / C# 2.0 (or above) I would have simply:

public class People : IEnumerable<Person> {
    /* snip */
    public IEnumerator<Person> GetEnumerator() {
        return ((IEnumerable<Person>)_people).GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator() { return _people.GetEnumerator();}
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文