|
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