假设以下类:
public class MyEnum: IEnumerator
{
private List<SomeObject> _myList = new List<SomeObject>();
...
}
有必要在 MyEnum 中实现 IEnumerator 方法。但是是否可以将 IEnumerator 的实现直接“委托”或重定向到 _myList 而无需实现 IEnumerator 方法?
方法一: 继续使用封装,将调用转发到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是首选。
你可以这样做:
public class MyEnum : IEnumerator {
private List<SomeObject> _myList = new List<SomeObject>();
public IEnumerator GetEnumerator() { return this._myList.GetEnumerator(); }
}
原因很简单。您的类可以包含多个作为集合的字段,因此编译器/环境无法知道应该使用哪个字段来实现“IEnumerator”。
EIDT:我同意@pb - 你应该实现 IEnumerator<SomeObject> 接口。
除了使用 pb 的方法之外,这是不可能的,原因很简单:接口方法需要传递一个this
指针作为第一个参数。当你调用GetEnumerator
你的对象时,这个指针就是你的对象。但是,为了使调用在嵌套列表上工作,指针必须是对该列表的引用,而不是您的类。
因此,您必须明确地将方法委托给另一个对象。
(顺便说一句,另一个回复中的建议是正确的:使用IEnumerator<T>
,而不是 IEnumerable
!)
如果要以调用者无法修改集合的方式返回集合,则可能需要将 List 包装到 ReadOnlyCollection<> 并返回 ReadOnlyCollection<> 的 IEnumerable<>。
这样您就可以确保您的收藏不会被更改。
除非你从 List<T> 派生。
public class MyEnum : List<SomeObject>, IEnumerable<SomeObject>{}
谢谢大家的意见和解释。最终,我将您对以下问题的一些答案结合在一起:
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();
}
}
该解决方案是为了确保调用代码无法修改列表,并且每个枚举器在各个方面都独立于其他枚举器(例如,使用排序)。再次感谢。
请注意,多亏了鸭子类型,您可以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());
}