2011-05-06 44 views
5

我假设以下示例给出了我们在实现IEnumberable接口时应遵循的最佳实践。C# - 为什么在实现IEnumberable接口时实现两个Current版本?

http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.movenext.aspx

这里有一个问题:

  1. 我们为什么要提供两个版本当前方法吗?
  2. 当版本ONE(对象IEnumerator.Current)被使用?
  3. 当使用TWO(公共人物当前)版本时?
  4. 如何在foreach语句中使用PeopleEnum。 //更新

谢谢

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

    // explicit interface implementation 
    object IEnumerator.Current /// **version ONE** 
    { 
     get 
     { 
      return Current; 
     } 
    } 

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

回答

2

我怀疑的原因是,此代码示例是从一个示例类实现IEnumerator<T>得出 - 如果示例类PeopleEnum实现IEnumerator<T>这种方法将需要:IEnumerator<T>继承IEnumerator所以你必须实行接口实现IEnumerator<T>时。

非通用IEnumerator的实施需要Current返回对象 - 在另一方面,强类型IEnumerator<T>需要电流返回类型T的实例 - 使用明确的,直观的界面实现能够满足需求的唯一途径。

+0

我刚刚发现你实际上给出了我需要的答案。 - 谢谢 – q0987 2011-05-07 02:27:56

7

IEnumerator.Current明确接口实现。

如果您将迭代器强制转换为IEnumerator(这是框架使用foreach执行的操作),则只能使用它。在其他情况下,将使用第二个版本。

你会看到它返回object,实际上使用返回Person的另一个实现。

第二个实现本身不是必需的接口,但这是为了方便,并且为了返回预期类型而不是object

+1

虽然所有这是正确的,你推断,投向IEnumerator是很少见的;它不是。 IEnumerable需要一个GetEnumerator()方法,该方法返回一个类型为IEnumerator的对象,并进行类型转换。几乎所有使用IEnumerables的内置代码(例如Linq的foreach和大部分代码)都会使用GetEnumerator()。 – KeithS 2011-05-06 21:05:11

+0

@KeithS - 公平点,我不是故意推断这一点。 – Oded 2011-05-06 21:10:57

1

版本2不是界面的一部分。您必须满足接口要求。

2

这是为了方便,例如。在while(p.MoveNext())循环中以类型安全方式使用PeopleEnum.Current,而不是显式地执行foreach枚举。

但是你需要做的唯一事情就是实现接口,如果你愿意,你可以隐式做到,但是有没有原因呢?如果我想在课堂上使用MovePrevious?如果我应该将对象投向Person,这会很酷吗?

如果你认为这个类可以用更多的操作方法扩展,Person Current是一件很酷的事情。

4

的IEnumerator的长篇实现不再需要:

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

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

    public IEnumerator GetEnumerator() 
    { 
     foreach (Person person in _people) 
      yield return person; 
    } 
} 

为了进一步把它带入21世纪,不使用非通用的IEnumerable:

public class PeopleEnum : IEnumerable<Person> 
{ 
    public Person[] _people; 

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

    public IEnumerator<Person> GetEnumerator() 
    { 
     foreach (Person person in _people) 
      yield return person; 
    } 

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