关于c#:您将如何实现IEnumerator接口?

关于c#:您将如何实现IEnumerator接口?

How would you implement the IEnumerator interface?

我有一个将对象映射到对象的类,但是与字典不同的是,它以两种方式映射它们。我现在正在尝试实现一个自定义的IEnumerator接口,该接口迭代这些值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public class Mapper<K,T> : IEnumerable< T >, IEnumerator< T >

{
    C5.TreeDictionary<K,T> KToTMap = new TreeDictionary<K,T>();
    C5.HashDictionary<T,K> TToKMap = new HashDictionary<T,K>();

    public void Add(K key, T value)
    {
        KToTMap.Add(key, value);
        TToKMap.Add(value, key);

    }

    public int Count
    {
        get { return KToTMap.Count; }
    }
   

    public K this[T obj]
    {
        get
        {
            return TToKMap[obj];
        }
    }

    public T this[K obj]
    {
        get
        {
            return KToTMap[obj];
        }
    }

    public IEnumerator< T > GetEnumerator()
    {
        return KToTMap.Values.GetEnumerator();
    }

    public T Current
    {
        get { throw new NotImplementedException(); }
    }

    public void Dispose()
    {
        throw new NotImplementedException();
    }

    object System.Collections.IEnumerator.Current
    {
        get { throw new NotImplementedException(); }
    }

    public bool MoveNext()
    {
        ;
    }

    public void Reset()
    {
        throw new NotImplementedException();
    }
}

首先,不要使您的集合对象实现IEnumerator <>。这会导致错误。 (考虑两个线程在同一个集合上进行迭代的情况)。

正确实现枚举数并非易事,因此C#2.0基于\\'yield return \\'语句添加了特殊的语言支持。

Raymond Chen的最新系列博客文章(" C#中迭代器的实现及其后果")是快速入门的好地方。

  • 第1部分:https://web.archive.org/web/20081216071723/http://blogs.msdn.com/oldnewthing/archive/2008/08/12/8849519.aspx
  • 第2部分:https://web.archive.org/web/20080907004812/http://blogs.msdn.com/oldnewthing/archive/2008/08/13/8854601.aspx
  • 第3部分:https://web.archive.org/web/20080824210655/http://blogs.msdn.com/oldnewthing/archive/2008/08/14/8862242.aspx
  • 第4部分:https://web.archive.org/web/20090207130506/http://blogs.msdn.com/oldnewthing/archive/2008/08/15/8868267.aspx

只需实现IEnumerable<T>接口。除非您想在枚举器中做一些特殊的事情,否则不需要实现IEnumerator<T>,对于您的情况,这似乎是不必要的。

1
2
3
4
5
6
public class Mapper<K,T> : IEnumerable< T > {
    public IEnumerator< T > GetEnumerator()
    {
        return KToTMap.Values.GetEnumerator();
    }
}

就是这样。


CreateEnumerable()返回实现GetEnumerator()

IEnumerable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class EasyEnumerable : IEnumerable<int> {

    IEnumerable<int> CreateEnumerable() {
        yield return 123;
        yield return 456;
        for (int i = 0; i < 6; i++) {
            yield return i;
        }//for
    }//method

    public IEnumerator<int> GetEnumerator() {
        return CreateEnumerable().GetEnumerator();
    }//method

    IEnumerator IEnumerable.GetEnumerator() {
        return CreateEnumerable().GetEnumerator();
    }//method

}//class


使用收益率回报率。

C#中的yield关键字是什么?


这里是" Robert Sedgewick的算法(第4版)"一书中的示例。

它是用Java编写的,我基本上用C#重写了它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
public class Stack< T > : IEnumerable< T >
{
    private T[] array;

    public Stack(int n)
    {
        array = new T[n];
    }

    public Stack()
    {
        array = new T[16];
    }

    public void Push(T item)
    {
        if (Count == array.Length)
        {
            Grow(array.Length * 2);
        }

        array[Count++] = item;
    }

    public T Pop()
    {
        if (Count == array.Length/4)
        {
            Shrink(array.Length/2);
        }

        return array[--Count];
    }

    private void Grow(int size)
    {
        var temp = array;
        array = new T[size];
        Array.Copy(temp, array, temp.Length);
    }

    private void Shrink(int size)
    {
        Array temp = array;
        array = new T[size];
        Array.Copy(temp,0,array,0,size);
    }

    public int Count { get; private set; }
    public IEnumerator< T > GetEnumerator()
    {
        return new ReverseArrayIterator(Count,array);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }


    // IEnumerator implementation
    private class ReverseArrayIterator : IEnumerator< T >
    {
        private int i;

        private readonly T[] array;

        public ReverseArrayIterator(int count,T[] array)
        {
            i = count;
            this.array = array;
        }

        public void Dispose()
        {

        }

        public bool MoveNext()
        {
            return i > 0;
        }

        public void Reset()
        {

        }

        public T Current { get { return array[--i]; } }

        object IEnumerator.Current
        {
            get { return Current; }
        }
    }
}

推荐阅读