简体   繁体   English

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

[英]How to delegate interface implementation to other class in C#

Assume the following class: 假设以下课程:

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

It is necessary to implement the IEnumerator methods in MyEnum. 有必要在MyEnum中实现IEnumerator方法。 But is it possible to 'delegate' or redirect the implementation for IEnumerator directly to _myList without needing to implement the IEnumerator methods? 但是,是否可以将IEnumerator的实现直接“委托”或重定向到_myList而无需实现IEnumerator方法?

Method 1: Continue to use encapsulation and forward calls to the List implementation. 方法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();
    }
}

Method 2: Inherit from List implementation you get that behavior for free. 方法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();
    }
}

Method 1 allows for better sandboxing as there is no method that will be called in List without MyEnum knowledge. 方法1允许更好的沙盒,因为在没有MyEnum知识的情况下没有将在List中调用的方法。 For least effort Method 2 is preferred. 最少努力方法2是优选的。

You can do this: 你可以这样做:

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

The reason is simple. 原因很简单。 Your class can contains several fields which are collections, so compiler/enviroment can't know which field should be used for implementing "IEnumerator". 您的类可以包含多个集合字段,因此编译器/环境无法知道应该使用哪个字段来实现“IEnumerator”。

EIDT: I agree with @pb - you should implements IEnumerator<SomeObject> interface. EIDT:我同意@pb - 你应该实现IEnumerator <SomeObject>接口。

Apart from using pb's method, this isn't possible for a “simple” reason: the interface method needs to get passed a this pointer as the first argument. 除了使用pb的方法之外,由于“简单”的原因,这是不可能的:接口方法需要传递一个this指针作为第一个参数。 When you call GetEnumerator on your object, this pointer will be your object. 当您在对象上调用GetEnumerator时,此指针将成为您的对象。 However, in order for the invocation to work on the nested list, the pointer would have to be a reference to that list, not your class. 但是,为了使调用在嵌套列表上工作,指针必须是对该列表的引用,而不是对您的类的引用。

Therefore you explicitly have to delegate the method to the other object. 因此,您必须明确地将该方法委托给另一个对象。

(And by the way, the advice in the other reply was right: use IEnumerator<T> , not IEnumerable !) (顺便说一句,其他回复中的建议是正确的:使用IEnumerator<T>而不是 IEnumerable !)

If you want return a collection in a way where the caller is unable to modify the collection, you might want to wrap the List into a ReadOnlyCollection<> and return IEnumerable<> of the ReadOnlyCollection<>. 如果要以调用者无法修改集合的方式返回集合,您可能希望将List包装到ReadOnlyCollection <>中并返回ReadOnlyCollection <>的IEnumerable <>。

This way you can be sure your collection will not be changed. 这样您就可以确保不会更改您的收藏。

除非您从List <T>派生。

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

Thank you all for your input and explanations. 谢谢大家的意见和解释。 Eventually I have combined some of your answers to the following: 最后,我将您的一些答案结合到以下内容中:

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

This solution is to ensure the calling code is incapable of modifying the list and each enumerator is independant of the others in every way (eg with sorting). 此解决方案是确保调用代码无法修改列表,并且每个枚举器在各方面都与其他枚举器无关(例如,使用排序)。 Thanks again. 再次感谢。

Note that thanks to duck-typing , you can use foreach on any object that has a GetEnumerator method - the object type need not actually implement IEnumerable . 请注意,由于duck-typing ,你可以在任何具有GetEnumerator方法的对象上使用foreach - 对象类型不需要实际实现IEnumerable

So if you do this: 所以,如果你这样做:

class SomeObject
{
}

 class MyEnum
 {
    private List<SomeObject> _myList = new List<SomeObject>();

    public IEnumerator<SomeObject> GetEnumerator()
    {
        return _myList.GetEnumerator();
    }
 }

Then this works just fine: 然后这很好用:

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