[英]How to delegate interface implementation to other class in C#
假设以下课程:
public class MyEnum: IEnumerator
{
private List<SomeObject> _myList = new List<SomeObject>();
...
}
有必要在MyEnum中实现IEnumerator方法。 但是,是否可以将IEnumerator的实现直接“委托”或重定向到_myList而无需实现IEnumerator方法?
方法1:继续使用封装并将调用转发到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();
}
}
此解决方案是确保调用代码无法修改列表,并且每个枚举器在各方面都与其他枚举器无关(例如,使用排序)。 再次感谢。
请注意,由于duck-typing ,你可以在任何具有GetEnumerator
方法的对象上使用foreach
- 对象类型不需要实际实现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());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.