|
1 | 1 | using System; |
| 2 | +using System.Linq; |
2 | 3 | using System.Collections; |
3 | | - |
4 | 4 | using System.Collections.Generic; |
5 | 5 |
|
6 | 6 | namespace NHibernate.Util |
7 | 7 | { |
8 | 8 | /// <summary> |
9 | | - /// Combines multiple objects implementing <see cref="IEnumerable"/> into one. |
| 9 | + /// Concatenates multiple objects implementing <see cref="IEnumerable"/> into one. |
10 | 10 | /// </summary> |
11 | | - public class JoinedEnumerable : IEnumerable, IEnumerator, IDisposable |
| 11 | + public class JoinedEnumerable : IEnumerable |
12 | 12 | { |
13 | 13 | private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof(JoinedEnumerable)); |
14 | 14 |
|
15 | | - private readonly IEnumerator[] _enumerators; |
16 | | - private int _current; |
| 15 | + private readonly IEnumerable[] _enumerables; |
17 | 16 |
|
18 | 17 | /// <summary> |
19 | 18 | /// Creates an IEnumerable object from multiple IEnumerables. |
20 | 19 | /// </summary> |
21 | 20 | /// <param name="enumerables">The IEnumerables to join together.</param> |
22 | 21 | public JoinedEnumerable(IEnumerable[] enumerables) |
23 | 22 | { |
24 | | - _enumerators = new IEnumerator[enumerables.Length]; |
25 | | - for (int i = 0; i < enumerables.Length; i++) |
26 | | - { |
27 | | - _enumerators[i] = enumerables[i].GetEnumerator(); |
28 | | - } |
29 | | - _current = 0; |
| 23 | + _enumerables = new IEnumerable[enumerables.Length]; |
| 24 | + Array.Copy(enumerables, _enumerables, enumerables.Length); |
30 | 25 | } |
31 | 26 |
|
32 | | - public JoinedEnumerable(List<IEnumerable> enumerables) |
| 27 | + public JoinedEnumerable(IEnumerable<IEnumerable> enumerables) |
33 | 28 | : this(enumerables.ToArray()) |
34 | 29 | { |
35 | 30 | } |
36 | 31 |
|
37 | 32 | public JoinedEnumerable(IEnumerable first, IEnumerable second) |
38 | | - : this(new IEnumerable[] { first, second }) |
| 33 | + : this(new[] { first, second }) |
39 | 34 | { |
40 | 35 | } |
41 | 36 |
|
42 | 37 |
|
43 | | - #region System.Collections.IEnumerator Members |
| 38 | + #region System.Collections.IEnumerable Members |
44 | 39 |
|
45 | 40 | /// <summary></summary> |
46 | | - public bool MoveNext() |
| 41 | + public IEnumerator GetEnumerator() |
47 | 42 | { |
48 | | - for (; _current < _enumerators.Length; _current++) |
49 | | - { |
50 | | - if (_enumerators[_current].MoveNext()) |
51 | | - { |
52 | | - return true; |
53 | | - } |
54 | | - else |
55 | | - { |
56 | | - // there are no items left to iterate over in the current |
57 | | - // enumerator so go ahead and dispose of it. |
58 | | - IDisposable disposable = _enumerators[_current] as IDisposable; |
59 | | - if (disposable != null) |
60 | | - { |
61 | | - disposable.Dispose(); |
62 | | - } |
63 | | - } |
64 | | - } |
65 | | - return false; |
| 43 | + var enumerators = _enumerables.Select(enumerable => enumerable.GetEnumerator()); |
| 44 | + return new JoinedEnumerator(enumerators); |
66 | 45 | } |
67 | 46 |
|
68 | | - /// <summary></summary> |
69 | | - public void Reset() |
| 47 | + #endregion |
| 48 | + |
| 49 | + |
| 50 | + |
| 51 | + #region Nested class JoinedEnumerator |
| 52 | + |
| 53 | + private class JoinedEnumerator : IEnumerator, IDisposable |
70 | 54 | { |
71 | | - for (int i = 0; i < _enumerators.Length; i++) |
| 55 | + private readonly IEnumerator[] _enumerators; |
| 56 | + private int _current; |
| 57 | + |
| 58 | + public JoinedEnumerator(IEnumerable<IEnumerator> enumerators) |
72 | 59 | { |
73 | | - _enumerators[i].Reset(); |
| 60 | + _enumerators = enumerators.ToArray(); |
| 61 | + _current = 0; |
74 | 62 | } |
75 | | - _current = 0; |
76 | | - } |
77 | 63 |
|
78 | | - /// <summary></summary> |
79 | | - public object Current |
80 | | - { |
81 | | - get { return _enumerators[_current].Current; } |
82 | | - } |
83 | 64 |
|
84 | | - #endregion |
| 65 | + #region System.Collections.IEnumerator Members |
85 | 66 |
|
86 | | - #region System.Collections.IEnumerable Members |
| 67 | + public bool MoveNext() |
| 68 | + { |
| 69 | + for (; _current < _enumerators.Length; _current++) |
| 70 | + { |
| 71 | + if (_enumerators[_current].MoveNext()) |
| 72 | + { |
| 73 | + return true; |
| 74 | + } |
| 75 | + else |
| 76 | + { |
| 77 | + // there are no items left to iterate over in the current |
| 78 | + // enumerator so go ahead and dispose of it. |
| 79 | + IDisposable disposable = _enumerators[_current] as IDisposable; |
| 80 | + if (disposable != null) |
| 81 | + { |
| 82 | + disposable.Dispose(); |
| 83 | + } |
| 84 | + } |
| 85 | + } |
| 86 | + return false; |
| 87 | + } |
87 | 88 |
|
88 | | - /// <summary></summary> |
89 | | - public IEnumerator GetEnumerator() |
90 | | - { |
91 | | - Reset(); |
92 | | - return this; |
93 | | - } |
94 | 89 |
|
95 | | - #endregion |
| 90 | + public void Reset() |
| 91 | + { |
| 92 | + foreach (var enumerator in _enumerators) |
| 93 | + enumerator.Reset(); |
| 94 | + _current = 0; |
| 95 | + } |
96 | 96 |
|
97 | | - #region IDisposable Members |
98 | 97 |
|
99 | | - /// <summary> |
100 | | - /// A flag to indicate if <c>Dispose()</c> has been called. |
101 | | - /// </summary> |
102 | | - private bool _isAlreadyDisposed; |
| 98 | + public object Current |
| 99 | + { |
| 100 | + get { return _enumerators[_current].Current; } |
| 101 | + } |
103 | 102 |
|
104 | | - /// <summary> |
105 | | - /// Finalizer that ensures the object is correctly disposed of. |
106 | | - /// </summary> |
107 | | - ~JoinedEnumerable() |
108 | | - { |
109 | | - Dispose(false); |
110 | | - } |
| 103 | + #endregion |
111 | 104 |
|
112 | | - /// <summary> |
113 | | - /// Takes care of freeing the managed and unmanaged resources that |
114 | | - /// this class is responsible for. |
115 | | - /// </summary> |
116 | | - public void Dispose() |
117 | | - { |
118 | | - log.Debug("running JoinedEnumerable.Dispose()"); |
119 | | - Dispose(true); |
120 | | - } |
| 105 | + #region IDisposable Members |
121 | 106 |
|
| 107 | + /// <summary> |
| 108 | + /// A flag to indicate if <c>Dispose()</c> has been called. |
| 109 | + /// </summary> |
| 110 | + private bool _isAlreadyDisposed; |
122 | 111 |
|
123 | | - /// <summary> |
124 | | - /// Takes care of freeing the managed and unmanaged resources that |
125 | | - /// this class is responsible for. |
126 | | - /// </summary> |
127 | | - /// <param name="isDisposing">Indicates if this JoinedEnumerable is being Disposed of or Finalized.</param> |
128 | | - /// <remarks> |
129 | | - /// The command is closed and the reader is disposed. This allows other ADO.NET |
130 | | - /// related actions to occur without needing to move all the way through the |
131 | | - /// EnumerableImpl. |
132 | | - /// </remarks> |
133 | | - protected virtual void Dispose(bool isDisposing) |
134 | | - { |
135 | | - if (_isAlreadyDisposed) |
| 112 | + /// <summary> |
| 113 | + /// Finalizer that ensures the object is correctly disposed of. |
| 114 | + /// </summary> |
| 115 | + ~JoinedEnumerator() |
136 | 116 | { |
137 | | - // don't dispose of multiple times. |
138 | | - return; |
| 117 | + Dispose(false); |
139 | 118 | } |
140 | 119 |
|
141 | | - // free managed resources that are being managed by the JoinedEnumerable if we |
142 | | - // know this call came through Dispose() |
143 | | - if (isDisposing) |
| 120 | + /// <summary> |
| 121 | + /// Takes care of freeing the managed and unmanaged resources that |
| 122 | + /// this class is responsible for. |
| 123 | + /// </summary> |
| 124 | + public void Dispose() |
144 | 125 | { |
145 | | - // dispose each IEnumerable that still needs to be disposed of |
146 | | - for (; _current < _enumerators.Length; _current++) |
| 126 | + log.Debug("running JoinedEnumerator.Dispose()"); |
| 127 | + Dispose(true); |
| 128 | + } |
| 129 | + |
| 130 | + |
| 131 | + /// <summary> |
| 132 | + /// Takes care of freeing the managed and unmanaged resources that |
| 133 | + /// this class is responsible for. |
| 134 | + /// </summary> |
| 135 | + /// <param name="isDisposing">Indicates if this JoinedEnumerable is being Disposed of or Finalized.</param> |
| 136 | + /// <remarks> |
| 137 | + /// The command is closed and the reader is disposed. This allows other ADO.NET |
| 138 | + /// related actions to occur without needing to move all the way through the |
| 139 | + /// EnumerableImpl. |
| 140 | + /// </remarks> |
| 141 | + private void Dispose(bool isDisposing) |
| 142 | + { |
| 143 | + if (_isAlreadyDisposed) |
147 | 144 | { |
148 | | - IDisposable currentDisposable = _enumerators[_current] as IDisposable; |
149 | | - if (currentDisposable != null) |
| 145 | + // don't dispose of multiple times. |
| 146 | + return; |
| 147 | + } |
| 148 | + |
| 149 | + // free managed resources that are being managed by the JoinedEnumerable if we |
| 150 | + // know this call came through Dispose() |
| 151 | + if (isDisposing) |
| 152 | + { |
| 153 | + // dispose each IEnumerable that still needs to be disposed of |
| 154 | + for (; _current < _enumerators.Length; _current++) |
150 | 155 | { |
151 | | - currentDisposable.Dispose(); |
| 156 | + IDisposable currentDisposable = _enumerators[_current] as IDisposable; |
| 157 | + if (currentDisposable != null) |
| 158 | + { |
| 159 | + currentDisposable.Dispose(); |
| 160 | + } |
152 | 161 | } |
153 | 162 | } |
154 | | - } |
155 | 163 |
|
156 | | - // free unmanaged resources here |
| 164 | + // free unmanaged resources here |
| 165 | + |
| 166 | + _isAlreadyDisposed = true; |
| 167 | + // nothing for Finalizer to do - so tell the GC to ignore it |
| 168 | + GC.SuppressFinalize(this); |
| 169 | + } |
157 | 170 |
|
158 | | - _isAlreadyDisposed = true; |
159 | | - // nothing for Finalizer to do - so tell the GC to ignore it |
160 | | - GC.SuppressFinalize(this); |
| 171 | + #endregion |
161 | 172 | } |
162 | 173 |
|
163 | 174 | #endregion |
164 | 175 | } |
165 | 176 |
|
| 177 | + |
| 178 | + |
| 179 | + |
166 | 180 | public class JoinedEnumerable<T> : IEnumerable<T> |
167 | 181 | { |
168 | 182 | private readonly IEnumerable<T>[] enumerables; |
@@ -195,7 +209,7 @@ IEnumerator<T> IEnumerable<T>.GetEnumerator() |
195 | 209 |
|
196 | 210 | public IEnumerator GetEnumerator() |
197 | 211 | { |
198 | | - return ((IEnumerable<T>) this).GetEnumerator(); |
| 212 | + return ((IEnumerable<T>)this).GetEnumerator(); |
199 | 213 | } |
200 | 214 |
|
201 | 215 | #endregion |
@@ -273,7 +287,7 @@ public void Reset() |
273 | 287 |
|
274 | 288 | public object Current |
275 | 289 | { |
276 | | - get { return ((IEnumerator<T>) this).Current; } |
| 290 | + get { return ((IEnumerator<T>)this).Current; } |
277 | 291 | } |
278 | 292 |
|
279 | 293 | #endregion |
|
0 commit comments