2008-09-24 25 views
8

假设下面的类:如何委托接口实现与其他类在C#

public class MyEnum: IEnumerator 
{ 
    private List<SomeObject> _myList = new List<SomeObject>(); 
... 
} 

有必要实施MyEnum的IEnumerator的方法。 但是是否可以将IEnumerator的实现直接委托给_myList而无需实现IEnumerator方法?

回答

7

方法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知识。费力最少方法2是优选的。

-1

不除非你从List < T>派生。

public class MyEnum : List<SomeObject>, IEnumerable<SomeObject>{} 
+0

好吧,这将工作,但我想肯定的是,调用代码是不能型铸造枚举器再次列出并添加或删除对象。 – Willem 2008-09-24 09:23:46

1

你可以这样做:

public class MyEnum : IEnumerator { 
    private List<SomeObject> _myList = new List<SomeObject>(); 
    public IEnumerator GetEnumerator() { return this._myList.GetEnumerator(); } 
} 

原因很简单。你的类可以包含几个属于集合的字段,所以编译器/环境无法知道应该使用哪个字段来实现“IEnumerator”。

EIDT:我同意@pb - 你应该实现IEnumerator <SomeObject>接口。

+0

要实现的接口是IEnumerable而不是IEnumerator。 – 2008-09-24 09:28:39

0

如果你想要的方式返回一个集合,其中来电者是无法修改集合,你可能希望将列表包装成一个ReadOnlyCollection <>和ReadOnlyCollection <的返回IEnumerable的<>>。

这样你可以确定你的收藏将不会改变。

1

除了使用pb的方法,这是不可能的一个“简单”的原因:接口方法需要通过this指针作为第一个参数。当您在对象上调用GetEnumerator时,此指针将成为您的对象。但是,为了使调用在嵌套列表上工作,指针必须是对该列表的引用,而不是您的类。

因此,您明确地必须将方法委托给其他对象。

(顺便提一句,在其他答复意见是正确的:使用IEnumerator<T>IEnumerable!)

-1

感谢大家的输入和解释。 最后,我已经联合一些你的答案以下几点:

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

该解决方案是确保调用的代码是不能修改的列表,每个枚举是别人的独立的以各种方式(例如使用排序) 。 再次感谢。

+0

您可以通过`ReadOnlyCollection`传递,因为`IEnumerable`永远不可改变!用户必须上传并猜测列表的原始类型才能对其进行修改。复制列表恕我直言,不是一个好主意。 – 2008-09-24 14:22:23

-1

指出,由于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()); 
} 
+0

我意识到这不是对原始问题的一般回答,但它与问题中提供的特定用例有关。 – yoyo 2017-06-07 20:43:02