wasSharp – Diff between revs 47 and 49

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 47 Rev 49
1 /////////////////////////////////////////////////////////////////////////// 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // 2 // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
3 // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // 3 // Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
4 // rights of fair usage, the disclaimer and warranty conditions. // 4 // rights of fair usage, the disclaimer and warranty conditions. //
5 /////////////////////////////////////////////////////////////////////////// 5 ///////////////////////////////////////////////////////////////////////////
6   6  
7 using System; 7 using System;
8 using System.Collections.Generic; 8 using System.Collections.Generic;
9 using System.Linq; 9 using System.Linq;
10   10  
11 namespace wasSharp.Linq 11 namespace wasSharp.Linq
12 { 12 {
13 public static class Extensions 13 public static class Extensions
14 { 14 {
15 /////////////////////////////////////////////////////////////////////////// 15 ///////////////////////////////////////////////////////////////////////////
16 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 16 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
17 /////////////////////////////////////////////////////////////////////////// 17 ///////////////////////////////////////////////////////////////////////////
18 /// <summary> 18 /// <summary>
19 /// A functional implementation of a switch clause. 19 /// A functional implementation of a switch clause.
20 /// </summary> 20 /// </summary>
21 /// <typeparam name="T">the type of items in the query</typeparam> 21 /// <typeparam name="T">the type of items in the query</typeparam>
22 /// <param name="query">the selector query</param> 22 /// <param name="query">the selector query</param>
23 /// <param name="default">the function to execute when no case matches</param> 23 /// <param name="default">the function to execute when no case matches</param>
24 /// <param name="case">a list of predicates representing the switch cases, 24 /// <param name="case">a list of predicates representing the switch cases,
25 /// where each predicate has to return True or False indicating whether 25 /// where each predicate has to return True or False indicating whether
26 /// fallthrough should occur. 26 /// fallthrough should occur.
27 /// </param> 27 /// </param>
28 /// <remarks>when used, the default action must be explicitly specified 28 /// <remarks>when used, the default action must be explicitly specified
29 /// due to language restrictions 29 /// due to language restrictions
30 /// </remarks> 30 /// </remarks>
31 public static void Switch<T>(this IEnumerable<T> query, 31 public static void Switch<T>(this IEnumerable<T> query,
32 // default 32 // default
33 Action<T> @default, 33 Action<T> @default,
34 // case 34 // case
35 // case 35 // case
36 // ... 36 // ...
37 params Predicate<T>[] @case) 37 params Predicate<T>[] @case)
38 { 38 {
39 if (@case.Length % 2 != 0) 39 if (@case.Length % 2 != 0)
40 throw new ArgumentException("Pairs of predicates expected."); 40 throw new ArgumentException("Pairs of predicates expected.");
41   41  
42 var enumerable = query as IList<T> ?? query.ToList(); 42 var enumerable = query as IList<T> ?? query.ToList();
43 using (var iter = enumerable.GetEnumerator()) 43 using (var iter = enumerable.GetEnumerator())
44 { 44 {
45 while (iter.MoveNext()) 45 while (iter.MoveNext())
46 { 46 {
47 var match = false; 47 var match = false;
48 for (var i = 0; i < @case.Length; i += 2) 48 for (var i = 0; i < @case.Length; i += 2)
49 { 49 {
50 if (!@case[i].Invoke(iter.Current)) 50 if (!@case[i].Invoke(iter.Current))
51 continue; 51 continue;
52   52  
53 if (@case[i + 1].Invoke(iter.Current)) 53 if (@case[i + 1].Invoke(iter.Current))
54 return; 54 return;
55   55  
56 match = true; 56 match = true;
57 } 57 }
58   58  
59 if (!match) 59 if (!match)
60 @default.Invoke(iter.Current); 60 @default.Invoke(iter.Current);
61 } 61 }
62 } 62 }
63 } 63 }
64   64  
65 /////////////////////////////////////////////////////////////////////////// 65 ///////////////////////////////////////////////////////////////////////////
66 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 66 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
67 /////////////////////////////////////////////////////////////////////////// 67 ///////////////////////////////////////////////////////////////////////////
68 /// <summary> 68 /// <summary>
-   69 /// A functional implementation of a switch clause.
-   70 /// </summary>
-   71 /// <typeparam name="T">the type of the item to query</typeparam>
-   72 /// <param name="query">the selector query</param>
-   73 /// <param name="default">the function to execute when no case matches</param>
-   74 /// <param name="case">a list of predicates representing the switch cases,
-   75 /// where each predicate has to return True or False indicating whether
-   76 /// fallthrough should occur.
-   77 /// </param>
-   78 /// <remarks>when used, the default action must be explicitly specified
-   79 /// due to language restrictions
-   80 /// </remarks>
-   81 public static void Switch<T>(this T query,
-   82 // default
-   83 Action<T> @default,
-   84 // case
-   85 // case
-   86 // ...
-   87 params Predicate<T>[] @case)
-   88 {
-   89 if (@case.Length % 2 != 0)
-   90 throw new ArgumentException("Pairs of predicates expected.");
-   91  
-   92 var match = false;
-   93 for (var i = 0; i < @case.Length; i += 2)
-   94 {
-   95 if (!@case[i].Invoke(query))
-   96 continue;
-   97  
-   98 if (@case[i + 1].Invoke(query))
-   99 return;
-   100  
-   101 match = true;
-   102 }
-   103  
-   104 if (!match)
-   105 @default.Invoke(query);
-   106  
-   107 }
-   108  
-   109 ///////////////////////////////////////////////////////////////////////////
-   110 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
-   111 ///////////////////////////////////////////////////////////////////////////
-   112 /// <summary>
69 /// Invokes pf in case the predicate p resolves or qf in case the predicate q resolves, or ef otherwise. 113 /// Invokes pf in case the predicate p resolves or qf in case the predicate q resolves, or ef otherwise.
70 /// </summary> 114 /// </summary>
71 /// <typeparam name="T">the type of items in the query</typeparam> 115 /// <typeparam name="T">the type of items in the query</typeparam>
72 /// <param name="query">the selector query</param> 116 /// <param name="query">the selector query</param>
73 /// <param name="p">the condition for invoking pf</param> 117 /// <param name="p">the condition for invoking pf</param>
74 /// <param name="pf">the action to invoke in case p resolves</param> 118 /// <param name="pf">the action to invoke in case p resolves</param>
75 /// <param name="q">the condition for invoking qf</param> 119 /// <param name="q">the condition for invoking qf</param>
76 /// <param name="qf">the action to invoke in case q resolves</param> 120 /// <param name="qf">the action to invoke in case q resolves</param>
77 /// <param name="ef">the action to invoke otherwise</param> 121 /// <param name="ef">the action to invoke otherwise</param>
78 public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> p, Action<T> pf, Predicate<T> q, Action<T> qf, Action<T> ef) 122 public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> p, Action<T> pf, Predicate<T> q, Action<T> qf, Action<T> ef)
79 { 123 {
80 query.ForAll(o => 124 query.ForAll(o =>
81 { 125 {
82 if (p.Invoke(o)) 126 if (p.Invoke(o))
83 { 127 {
84 pf.Invoke(o); 128 pf.Invoke(o);
85 } 129 }
86 else if (q.Invoke(o)) 130 else if (q.Invoke(o))
87 { 131 {
88 qf.Invoke(o); 132 qf.Invoke(o);
89 } 133 }
90 else 134 else
91 { 135 {
92 ef.Invoke(o); 136 ef.Invoke(o);
93 } 137 }
94 }); 138 });
95 } 139 }
96   140  
97 /////////////////////////////////////////////////////////////////////////// 141 ///////////////////////////////////////////////////////////////////////////
98 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 142 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
99 /////////////////////////////////////////////////////////////////////////// 143 ///////////////////////////////////////////////////////////////////////////
100 /// <summary> 144 /// <summary>
101 /// Invokes pf in case the predicate p resolves or qf in case the predicate q resolves. 145 /// Invokes pf in case the predicate p resolves or qf in case the predicate q resolves.
102 /// </summary> 146 /// </summary>
103 /// <typeparam name="T">the type of items in the query</typeparam> 147 /// <typeparam name="T">the type of items in the query</typeparam>
104 /// <param name="query">the selector query</param> 148 /// <param name="query">the selector query</param>
105 /// <param name="p">the condition for invoking pf</param> 149 /// <param name="p">the condition for invoking pf</param>
106 /// <param name="pf">the action to invoke in case p resolves</param> 150 /// <param name="pf">the action to invoke in case p resolves</param>
107 /// <param name="q">the condition for invoking qf</param> 151 /// <param name="q">the condition for invoking qf</param>
108 /// <param name="qf">the action to invoke in case q resolves</param> 152 /// <param name="qf">the action to invoke in case q resolves</param>
109 public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> p, Action<T> pf, Predicate<T> q, Action<T> qf) 153 public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> p, Action<T> pf, Predicate<T> q, Action<T> qf)
110 { 154 {
111 query.ForAll(o => 155 query.ForAll(o =>
112 { 156 {
113 if (p.Invoke(o)) 157 if (p.Invoke(o))
114 { 158 {
115 pf.Invoke(o); 159 pf.Invoke(o);
116 return; 160 return;
117 } 161 }
118   162  
119 if (q.Invoke(o)) 163 if (q.Invoke(o))
120 { 164 {
121 qf.Invoke(o); 165 qf.Invoke(o);
122 return; 166 return;
123 } 167 }
124 }); 168 });
125 } 169 }
126   170  
127 /////////////////////////////////////////////////////////////////////////// 171 ///////////////////////////////////////////////////////////////////////////
128 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 172 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
129 /////////////////////////////////////////////////////////////////////////// 173 ///////////////////////////////////////////////////////////////////////////
130 /// <summary> 174 /// <summary>
131 /// Invokes pass if and only if predicate resovles or fail otherwise. 175 /// Invokes pass if and only if predicate resovles or fail otherwise.
132 /// </summary> 176 /// </summary>
133 /// <typeparam name="T">the type of items in the query</typeparam> 177 /// <typeparam name="T">the type of items in the query</typeparam>
134 /// <param name="query">the selector query</param> 178 /// <param name="query">the selector query</param>
135 /// <param name="condition">the condition for invoking pf</param> 179 /// <param name="condition">the condition for invoking pf</param>
136 /// <param name="pass">the function to invoke in case the predicate resolves</param> 180 /// <param name="pass">the function to invoke in case the predicate resolves</param>
137 /// <param name="fail">the function to invoke otherwise</param> 181 /// <param name="fail">the function to invoke otherwise</param>
138 public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> condition, Action<T> pass, Action<T> fail) 182 public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> condition, Action<T> pass, Action<T> fail)
139 { 183 {
140 query.ForAll(o => 184 query.ForAll(o =>
141 { 185 {
142 switch (condition.Invoke(o)) 186 switch (condition.Invoke(o))
143 { 187 {
144 case true: 188 case true:
145 pass.Invoke(o); 189 pass.Invoke(o);
146 return; 190 return;
147   191  
148 default: 192 default:
149 fail.Invoke(o); 193 fail.Invoke(o);
150 return; 194 return;
151 } 195 }
152 }); 196 });
153 } 197 }
154   198  
155 /////////////////////////////////////////////////////////////////////////// 199 ///////////////////////////////////////////////////////////////////////////
156 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 200 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
157 /////////////////////////////////////////////////////////////////////////// 201 ///////////////////////////////////////////////////////////////////////////
158 /// <summary> 202 /// <summary>
159 /// Invokes pass if and only if condition holds or fail otherwise. 203 /// Invokes pass if and only if condition holds or fail otherwise.
160 /// </summary> 204 /// </summary>
161 /// <typeparam name="T">the return type of the pass and fail functions</typeparam> 205 /// <typeparam name="T">the return type of the pass and fail functions</typeparam>
162 /// <param name="condition">the branch condition</param> 206 /// <param name="condition">the branch condition</param>
163 /// <param name="pass">function with no parameters and return type T in case condition passes</param> 207 /// <param name="pass">function with no parameters and return type T in case condition passes</param>
164 /// <param name="fail">function with no parameters and return type T in case condition fails</param> 208 /// <param name="fail">function with no parameters and return type T in case condition fails</param>
165 /// <returns>the result of pass in case condition holds or the result of fail otherwise</returns> 209 /// <returns>the result of pass in case condition holds or the result of fail otherwise</returns>
166 public static T IfElse<T>(this bool condition, Func<T> pass, Func<T> fail) 210 public static T IfElse<T>(this bool condition, Func<T> pass, Func<T> fail)
167 { 211 {
168 return condition ? pass.Invoke() : fail.Invoke(); 212 return condition ? pass.Invoke() : fail.Invoke();
169 } 213 }
170   214  
171 /////////////////////////////////////////////////////////////////////////// 215 ///////////////////////////////////////////////////////////////////////////
172 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 216 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
173 /////////////////////////////////////////////////////////////////////////// 217 ///////////////////////////////////////////////////////////////////////////
174 /// <summary> 218 /// <summary>
175 /// Invokes pass if and only if condition holds or fail otherwise. 219 /// Invokes pass if and only if condition holds or fail otherwise.
176 /// </summary> 220 /// </summary>
177 /// <typeparam name="U">the type of the argument to pass and fail</typeparam> 221 /// <typeparam name="U">the type of the argument to pass and fail</typeparam>
178 /// <typeparam name="V">the return type of pass and fail</typeparam> 222 /// <typeparam name="V">the return type of pass and fail</typeparam>
179 /// <param name="condition">the branch condition</param> 223 /// <param name="condition">the branch condition</param>
180 /// <param name="pass">function that takes argument arg and returns type V in case condition holds</param> 224 /// <param name="pass">function that takes argument arg and returns type V in case condition holds</param>
181 /// <param name="fail">function that takes argument arg and returns type V in case condition fails</param> 225 /// <param name="fail">function that takes argument arg and returns type V in case condition fails</param>
182 /// <param name="arg">the argument passed to pass or fail functions</param> 226 /// <param name="arg">the argument passed to pass or fail functions</param>
183 /// <returns>the result of pass in case condition holds or the result of fail otherwise</returns> 227 /// <returns>the result of pass in case condition holds or the result of fail otherwise</returns>
184 public static V IfElse<U, V>(this bool condition, Func<U, V> pass, Func<U, V> fail, U arg = default(U)) 228 public static V IfElse<U, V>(this bool condition, Func<U, V> pass, Func<U, V> fail, U arg = default(U))
185 { 229 {
186 return condition ? pass.Invoke(arg) : fail.Invoke(arg); 230 return condition ? pass.Invoke(arg) : fail.Invoke(arg);
187 } 231 }
188   232  
189 /////////////////////////////////////////////////////////////////////////// 233 ///////////////////////////////////////////////////////////////////////////
190 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 234 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
191 /////////////////////////////////////////////////////////////////////////// 235 ///////////////////////////////////////////////////////////////////////////
192 /// <summary> 236 /// <summary>
193 /// Invokes pass if and only if condition holds or fail otherwise. 237 /// Invokes pass if and only if condition holds or fail otherwise.
194 /// </summary> 238 /// </summary>
195 /// <typeparam name="T">the type of the argument to pass and fail</typeparam> 239 /// <typeparam name="T">the type of the argument to pass and fail</typeparam>
196 /// <param name="condition">the branch condition</param> 240 /// <param name="condition">the branch condition</param>
197 /// <param name="pass">function that takes argument arg and returns nothing in case condition holds</param> 241 /// <param name="pass">function that takes argument arg and returns nothing in case condition holds</param>
198 /// <param name="fail">function that takes argument arg and returns nothing in case condition fails</param> 242 /// <param name="fail">function that takes argument arg and returns nothing in case condition fails</param>
199 /// <param name="arg">the optional argument passed to pass or fail functions</param> 243 /// <param name="arg">the optional argument passed to pass or fail functions</param>
200 public static void IfElse<T>(this bool condition, Action<T> pass, Action<T> fail, T arg = default(T)) 244 public static void IfElse<T>(this bool condition, Action<T> pass, Action<T> fail, T arg = default(T))
201 { 245 {
202 switch (condition) 246 switch (condition)
203 { 247 {
204 case true: 248 case true:
205 pass.Invoke(arg); 249 pass.Invoke(arg);
206 return; 250 return;
207   251  
208 default: 252 default:
209 fail.Invoke(arg); 253 fail.Invoke(arg);
210 return; 254 return;
211 } 255 }
212 } 256 }
213   257  
214 /////////////////////////////////////////////////////////////////////////// 258 ///////////////////////////////////////////////////////////////////////////
215 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 259 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
216 /////////////////////////////////////////////////////////////////////////// 260 ///////////////////////////////////////////////////////////////////////////
217 /// <summary> 261 /// <summary>
218 /// Invokes pass if and only if condition holds or fail otherwise. 262 /// Invokes pass if and only if condition holds or fail otherwise.
219 /// </summary> 263 /// </summary>
220 /// <typeparam name="U">the type of the first argument to the pass or fail functions</typeparam> 264 /// <typeparam name="U">the type of the first argument to the pass or fail functions</typeparam>
221 /// <typeparam name="V">the type of the second argument to the pass or fail functions</typeparam> 265 /// <typeparam name="V">the type of the second argument to the pass or fail functions</typeparam>
222 /// <param name="condition">the branch condition</param> 266 /// <param name="condition">the branch condition</param>
223 /// <param name="pass">function that takes argument arg and returns nothing in case condition holds</param> 267 /// <param name="pass">function that takes argument arg and returns nothing in case condition holds</param>
224 /// <param name="fail">function that takes argument arg and returns nothing in case condition fails</param> 268 /// <param name="fail">function that takes argument arg and returns nothing in case condition fails</param>
225 /// <param name="arga">first optional argument passed to pass or fail functions</param> 269 /// <param name="arga">first optional argument passed to pass or fail functions</param>
226 /// <param name="argb">second optional argument passed to pass or fail functions</param> 270 /// <param name="argb">second optional argument passed to pass or fail functions</param>
227 public static void IfElse<U, V>(this bool condition, Action<U, V> pass, Action<U, V> fail, U arga = default(U), V argb = default(V)) 271 public static void IfElse<U, V>(this bool condition, Action<U, V> pass, Action<U, V> fail, U arga = default(U), V argb = default(V))
228 { 272 {
229 switch (condition) 273 switch (condition)
230 { 274 {
231 case true: 275 case true:
232 pass.Invoke(arga, argb); 276 pass.Invoke(arga, argb);
233 return; 277 return;
234   278  
235 default: 279 default:
236 fail.Invoke(arga, argb); 280 fail.Invoke(arga, argb);
237 return; 281 return;
238 } 282 }
239 } 283 }
240   284  
241 /////////////////////////////////////////////////////////////////////////// 285 ///////////////////////////////////////////////////////////////////////////
242 // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // 286 // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 //
243 /////////////////////////////////////////////////////////////////////////// 287 ///////////////////////////////////////////////////////////////////////////
244 /// <summary> 288 /// <summary>
245 /// Returns true of an enumerable contains more than one element. 289 /// Returns true of an enumerable contains more than one element.
246 /// </summary> 290 /// </summary>
247 /// <typeparam name="T">the type of the enumeration</typeparam> 291 /// <typeparam name="T">the type of the enumeration</typeparam>
248 /// <param name="e">the enumeration</param> 292 /// <param name="e">the enumeration</param>
249 /// <returns>true if enumeration contains more than one element</returns> 293 /// <returns>true if enumeration contains more than one element</returns>
250 /// <remarks>O(2) worst case</remarks> 294 /// <remarks>O(2) worst case</remarks>
251 public static bool Some<T>(this IEnumerable<T> e) 295 public static bool Some<T>(this IEnumerable<T> e)
252 { 296 {
253 var i = 0; 297 var i = 0;
254 using (var iter = e.GetEnumerator()) 298 using (var iter = e.GetEnumerator())
255 { 299 {
256 while (iter.MoveNext()) 300 while (iter.MoveNext())
257 { 301 {
258 if (++i > 1) 302 if (++i > 1)
259 return true; 303 return true;
260 } 304 }
261 return false; 305 return false;
262 } 306 }
263 } 307 }
264   308  
265 /// <summary> 309 /// <summary>
266 /// Sequentially removes all the elements from the first sequence that are in the second sequence 310 /// Sequentially removes all the elements from the first sequence that are in the second sequence
267 /// or all the elements from the second sequence that are in the first sequence. 311 /// or all the elements from the second sequence that are in the first sequence.
268 /// </summary> 312 /// </summary>
269 /// <typeparam name="T">the type o the collection</typeparam> 313 /// <typeparam name="T">the type o the collection</typeparam>
270 /// <param name="o">the first sequence to remove from</param> 314 /// <param name="o">the first sequence to remove from</param>
271 /// <param name="p">the second sequence to remove</param> 315 /// <param name="p">the second sequence to remove</param>
272 /// <returns>the first sequence excluding the second sequence or the second sequence excluding the first sequence</returns> 316 /// <returns>the first sequence excluding the second sequence or the second sequence excluding the first sequence</returns>
273 public static IEnumerable<T> SequenceExceptAny<T>(this IEnumerable<T> o, IEnumerable<T> p) where T : IEquatable<T> 317 public static IEnumerable<T> SequenceExceptAny<T>(this IEnumerable<T> o, IEnumerable<T> p) where T : IEquatable<T>
274 { 318 {
275 var l = new List<T>(o); 319 var l = new List<T>(o);
276 var r = new List<T>(p); 320 var r = new List<T>(p);
277 return l.Count > r.Count 321 return l.Count > r.Count
278 ? l.Zip(r, (x, y) => x.Equals(y) ? default(T) : y) 322 ? l.Zip(r, (x, y) => x.Equals(y) ? default(T) : y)
279 .Concat(l.Skip(r.Count)) 323 .Concat(l.Skip(r.Count))
280 .Where(q => q != null && !q.Equals(default(T))) 324 .Where(q => q != null && !q.Equals(default(T)))
281 : r.Zip(l, (x, y) => x.Equals(y) ? default(T) : y) 325 : r.Zip(l, (x, y) => x.Equals(y) ? default(T) : y)
282 .Concat(r.Skip(l.Count)) 326 .Concat(r.Skip(l.Count))
283 .Where(q => q != null && !q.Equals(default(T))); 327 .Where(q => q != null && !q.Equals(default(T)));
284 } 328 }
285   329  
286 /// <summary> 330 /// <summary>
287 /// Sequentially removes all the elements from the first sequence that are in the second sequence. 331 /// Sequentially removes all the elements from the first sequence that are in the second sequence.
288 /// </summary> 332 /// </summary>
289 /// <typeparam name="T">the type o the collection</typeparam> 333 /// <typeparam name="T">the type o the collection</typeparam>
290 /// <param name="o">the first sequence to remove from</param> 334 /// <param name="o">the first sequence to remove from</param>
291 /// <param name="p">the second sequence to remove</param> 335 /// <param name="p">the second sequence to remove</param>
292 /// <returns>the first sequence excluding the second sequence</returns> 336 /// <returns>the first sequence excluding the second sequence</returns>
293 public static IEnumerable<T> SequenceExcept<T>(this IEnumerable<T> a, IEnumerable<T> b) where T : IEquatable<T> 337 public static IEnumerable<T> SequenceExcept<T>(this IEnumerable<T> a, IEnumerable<T> b) where T : IEquatable<T>
294 { 338 {
295 using (var ea = a.GetEnumerator()) 339 using (var ea = a.GetEnumerator())
296 { 340 {
297 using (var eb = b.GetEnumerator()) 341 using (var eb = b.GetEnumerator())
298 { 342 {
299 while (ea.MoveNext()) 343 while (ea.MoveNext())
300 { 344 {
301 if (eb.MoveNext() && ea.Current.Equals(eb.Current)) 345 if (eb.MoveNext() && ea.Current.Equals(eb.Current))
302 continue; 346 continue;
303 yield return ea.Current; 347 yield return ea.Current;
304 } 348 }
305 } 349 }
306 } 350 }
307 } 351 }
308 } 352 }
309 } 353 }
310   354