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

时间:2008-09-24 09:14:17

标签: c# interface

假设以下课程:

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

有必要在MyEnum中实现IEnumerator方法。 但是,是否可以将IEnumerator的实现直接“委托”或重定向到_myList而无需实现IEnumerator方法?

7 个答案:

答案 0 :(得分: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知识的情况下,没有方法可以在List中调用。最少努力方法2 是首选。

答案 1 :(得分:1)

你可以这样做:

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

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

EIDT:我同意@pb - 你应该实现IEnumerator&lt; SomeObject&gt;接口

答案 2 :(得分:1)

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

因此,您必须明确地将该方法委托给另一个对象。

(顺便说一句,其他回复中的建议是正确的:使用IEnumerator<T> IEnumerable!)

答案 3 :(得分:0)

如果要以调用者无法修改集合的方式返回集合,您可能希望将List包装到ReadOnlyCollection&lt;&gt;中。并返回IEnumerable&lt;&gt; ReadOnlyCollection&lt;&gt;。

通过这种方式,您可以确保不会更改您的收藏。

答案 4 :(得分:-1)

除非您从List&lt; T&gt;派生。

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

答案 5 :(得分:-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();
    }
}

此解决方案是确保调用代码无法修改列表,并且每个枚举器在各方面都与其他枚举器无关(例如,使用排序)。 再次感谢。

答案 6 :(得分:-1)

请注意,感谢duck-typing,您可以对任何具有routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Welcome", action = "Index", id = UrlParameter.Optional } ); 方法的对象使用foreach - 对象类型无需实际实现GetEnumerator

所以,如果你这样做:

IEnumerable

然后这很好用:

class SomeObject
{
}

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

    public IEnumerator<SomeObject> GetEnumerator()
    {
        return _myList.GetEnumerator();
    }
 }
相关问题