C# - 为什么在实现 IEnumerable 接口时实现两个版本的 Current
本文关键字:实现 两个 版本 Current 为什么 IEnumerable 接口 | 更新日期: 2023-09-27 17:55:27
我假设以下示例提供了我们在实现 IEnumerable 接口时应遵循的最佳实践。
https://learn.microsoft.com/en-us/dotnet/api/system.collections.ienumerator.movenext
问题是:
- 为什么我们应该提供两个版本的当前方法?
- 何时使用版本 ONE(对象 IEnumerator.Current)?
- 何时使用版本TWO(公共人员当前)?
- 如何在 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();
}
}
}
}
IEnumerator.Current
是一个显式接口实现。
仅当将迭代器转换为IEnumerator
时,才能使用它(这是框架对foreach
所做的)。在其他情况下,将使用第二个版本。
您将看到它返回object
并且实际上使用返回Person
的另一个实现。
接口本身不需要第二个实现,但为了方便起见,为了返回预期的类型而不是object
。
不再需要 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();
}
}
我怀疑原因是这个代码示例是从实现IEnumerator<T>
的示例类派生的 - 如果示例类PeopleEnum
IEnumerator<T>
实现的,则需要这种方法:IEnumerator<T>
继承IEnumerator
因此您必须在实现IEnumerator<T>
时实现这两个接口。
非泛型IEnumerator
的实现需要Current
返回对象 - 另一方面,强类型IEnumerator<T>
要求 Current 返回类型 T
的实例 - 使用显式和直接接口实现是满足这两个要求的唯一方法。
它是为了方便,例如。 在一段时间(p.MoveNext())循环中以类型安全的方式使用PeopleEnum.Current,而不是显式执行foreach枚举。
但是您唯一需要做的就是实现接口,如果您愿意,您可以隐式执行此操作,但是有原因吗?如果我想在课堂上使用 MovePrior?如果我应该将对象投射(拆箱)给人会很酷吗?
如果你认为这个类可以用更多的操作方法来扩展,那么Person Current是一件很酷的事情。
版本二不是界面的一部分。您必须满足接口要求。