繁体   English   中英

如何在C#中将接口实现委托给其他类

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM