簡體   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