{"id":604,"date":"2013-07-22T13:52:06","date_gmt":"2013-07-22T13:52:06","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=604"},"modified":"2014-08-14T20:32:30","modified_gmt":"2014-08-14T20:32:30","slug":"ixinteractive-extensions","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/ixinteractive-extensions\/","title":{"rendered":"Ix\/Interactive Extensions"},"content":{"rendered":"<p>I&#8217;m a bit late to the party with this one &#8211; Ix or Interactive Extensions.<\/p>\n<p>Available on NuGet via the Ix-Main package. This will give us the System.Interactive assembly.<\/p>\n<p>Ix are basically a bunch of extension methods for IEnumerable and the<br \/>\nEnumerableEx class. I&#8217;m sure many of us have written IEnumerable extensions to supply a ForEach extension method or the likes. Well Ix gives us that and more.<\/p>\n<p>In this post I will not be documenting each overload but will try to give an idea of what the methods might be used for and how to use them. Checking which overload is suitable is down to the reader.<\/p>\n<p><em>Note: some of the examples may be less than useful, I will attempt to update with better examples as\/when I come up with them.<\/em><\/p>\n<p><strong>Buffer<\/strong><\/p>\n<p>Basically takes an IEnumerable and creates an IEnumerable of IList of type T of the given buffer size. <\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new int&#x5B;] { 3, 5, 6, 2, 76, 45, 32, 1, 6, 3, 89, 100 };\r\nIEnumerable&lt;IList&lt;int&gt;&gt; lists = items.Buffer(3);\r\n<\/pre>\n<p>The above would result in an IEnumerable with 4 ILists of type T each containing up to 3 items each. An overload of this method exists which allows you to skip a number of elements at the start of each  buffer.<\/p>\n<p><strong>Case<\/strong><\/p>\n<p>Case is a static method on EnumerableEx and allows us to pass in an argument to compare against and an IDictionary of keys &#8211; which will be used to match with the argument passed into the Case method and it will return an IEnumerable relating to the values which appear in the dictionary against the given key. So for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIDictionary&lt;int, IEnumerable&lt;string&gt;&gt; d = new Dictionary&lt;int, IEnumerable&lt;string&gt;&gt;\r\n{\r\n   {5, new&#x5B;] {&quot;Five&quot;}},\r\n   {4, new&#x5B;] {&quot;Four&quot;}},\r\n   {1, new&#x5B;] {&quot;One&quot;}},\r\n   {2, new&#x5B;] {&quot;Two&quot;}},\r\n   {3, new&#x5B;] {&quot;Three&quot;}},\r\n};\r\n\r\nvar matches = EnumerableEx.Case(() =&gt; 4, d);\r\n<\/pre>\n<p>In the above, matches will contain the IEnumerable<string> of the values stored in the dictionary against the key 4, in other words the IEnumerable containing the string &#8220;Four&#8221;.<\/p>\n<p>An overload of this method allows you to supply an IEnumerable to act as the default values should a match against the selector not be found.<\/p>\n<p><strong>Create<\/strong><\/p>\n<p>Create is a static method on the EnumerableEx class which allows us to create an IEnumerable from a IEnumerator (or via an overload from an IYielder).<\/p>\n<p>Let&#8217;s assume we have a method that returns an IEnumerator of integers, here&#8217;s a mock up of such a method<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nprivate static IEnumerator&lt;int&gt; Factory()\r\n{\r\n   yield return 1;\r\n   yield return 2;\r\n   yield return 3;\r\n   yield return 4;\r\n}\r\n<\/pre>\n<p>Now using Ix we can create an IEnumerable of integers using<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar items = EnumerableEx.Create(Factory);\r\n<\/pre>\n<p><strong>Defer<\/strong><\/p>\n<p>As the name suggests Defer will defer the creation of an enumerable sequence until a call to GetEnumerator, so for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar items = EnumerableEx.Defer(() =&gt; new &#x5B;] { 3, 5, 6, 2 });\r\n<\/pre>\n<p>the code above will not call the enumerable factory method (in this case the anonymous method creating an array of integers) until the GetEnumerator is called.<\/p>\n<p><strong>Catch<\/strong><\/p>\n<p>Creates an IEnumerable sequence based on the source, but if the source has an exception will switch to the second IEnumerable.<\/p>\n<p>A somewhat convoluted sample below<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; GetNegatives()\r\n{ \r\n   int&#x5B;] items = new int&#x5B;] { -1, -2, 0, -3 };\r\n   for (int i = 0; i &lt; items.Length; i++)\r\n   {\r\n      if (items&#x5B;i] &gt;= 0)\r\n         throw new Exception();\r\n\r\n      yield return items&#x5B;i];\r\n   }\r\n}\r\n\r\nIEnumerable&lt;int&gt; items = new int&#x5B;] { 3, 5, 6, 2, 76, 45, 32, 1, 6, 3, 89, 100 };\r\nIEnumerable&lt;int&gt; e = GetNegatives().Catch(items);\r\n<\/pre>\n<p>The above will create an IEnumerable e that contains -1, -2 and then the values from the items IEnumerable.<\/p>\n<p>There are several overloads of the Catch method to check out.<\/p>\n<p><strong>Distinct<\/strong><\/p>\n<p>Returns an IEnumerable of the distinct values in a sequence<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new int&#x5B;] { 3, 5, 6, 2, 76, 45, 32, 1, 6, 3, 89, 100 };\r\nIEnumerable&lt;int&gt; distinct = items.Distinct();\r\n<\/pre>\n<p>The above will result in a sequence 3, 5, 6, 2, 76, 45, 32, 1, 89, 100 removing the duplicates.<\/p>\n<p><strong>DistinctUntilChanged<\/strong><\/p>\n<p>Returns consecutive distinct values<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new int&#x5B;] { 3, 3, 3, 5, 5, 2, 76, 76, 100 };\r\nIEnumerable&lt;int&gt; distinct = items.DistinctUntilChanged();\r\n<\/pre>\n<p>The above will return an sequence 3, 5, 2, 76, 100<\/p>\n<p><strong>Do<\/strong><\/p>\n<p>Several overloads of the Do method exist, we&#8217;ll just take a look at the one which takes an Action. Do will simply invoke some action on each item within the IEnumerable, so for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new int&#x5B;] { 3, 5, 6, 2, 76 };\r\nitems.Do(Console.WriteLine);\r\n<\/pre>\n<p>the above code will simply call WriteLine on each integer within the items IEnumerable. However, this is lazy and hence we actually need to do something with the items returns enumerable.<\/p>\n<p><strong>DoWhile<\/strong><\/p>\n<p>The DoWhile method iterates over an IEnumerable whilst the supplied function is true, so for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar items = new int&#x5B;] { 3, 5, 6, 2 };\r\n\r\nint i = 0;\r\nvar results = items.DoWhile(() =&gt; i++ &lt; 2);\r\nint len = results.Count();\r\n<\/pre>\n<p>If we run this code the <em>len<\/em> variable will be 12 as the DoWhile looped through the IEnumerable 3 times and the <em>items<\/em> array contained four items. So basically if we output to the console each item returned by <em>results<\/em> will see the array items output three times.<\/p>\n<p><strong>Expand<\/strong><\/p>\n<p>Expand, basically loops through the supplied IEnumerable (possibly infinitely if you do not use a Take or similar method to stop it). In essence is applies a selector function each time through the enumerable changing the values. <\/p>\n<p>So imagine we have an array of values 1, 2 and 0 and apply Expand to this as follows<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar items = new &#x5B;] { 1, 2, 0 };\r\nvar results = items.Expand(i =&gt; new&#x5B;] {i + 1}).Take(9);\r\n<\/pre>\n<p>what happens here is the output (if we ran <em>results.ForEach(Console.WriteLine)<\/em>) will output 1, 2, 0 (the values from <em>items<\/em> then 2, 3, 1 and finally 3, 4, 2. As you see each time we iterate through we add 1 to each element.<\/p>\n<p><strong>Finally<\/strong><\/p>\n<p>Finally can be used on a sequence so that an action may be invoked upon the termination or disposal, so for example the following will output the sequence to the console then output &#8220;Completed&#8221;<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 5, 6, 2, 76 };\r\n\r\nitems.Finally(() =&gt; Console.WriteLine(&quot;Completed&quot;)).ForEach(Console.WriteLine);\r\n<\/pre>\n<p><strong>For<\/strong><\/p>\n<p>The For method takes a source enumerable and applies a supplied enumerable to it, so a simple example might be <\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new int&#x5B;] { 3, 5, 6, 2, 76 };\r\nEnumerableEx.For(items, i =&gt; new &#x5B;]{i + 1, i + 2});\r\n<\/pre>\n<p>In this case each item in the <em>items<\/em> enumerable will have the <em>new []{i + 1, i + 2}<\/em> applied to it, thus output for this would be<\/p>\n<p>4, 5, 6, 7, 7, 8, 3, 4, 77, 78<\/p>\n<p>the first item 3 in the source enumerable is sent to the For method and we get back a transformed value as two values 3 + 1 and then 3 + 2 and so on.<\/p>\n<p><strong>ForEach<\/strong><\/p>\n<p>ForEach will invoke an action on each item within an IEnumerable, so a simple example might be to just write a more compact foreach to write output to the console, i.e.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new int&#x5B;] { 3, 5, 6, 2, 76 };\r\nitems.ForEach(Console.WriteLine);\r\n<\/pre>\n<p><strong>Generate<\/strong><\/p>\n<p>As the name suggests, <em>Generate<\/em> can be used to generate a sequence in a similar way to a for loop might be used, here&#8217;s an example which creates an IEnumerable with the range [10, 20]<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nEnumerableEx.Generate(10, i =&gt; i &lt;= 20, i =&gt; i + 1, i =&gt; i)\r\n<\/pre>\n<p>The first argument is the starting value, then we have the condition to stop the generator, next we have the state update function, in this case we&#8217;re incrementing the state by 1, finally we have the result function, in this case we&#8217;re just using the supplied state value.<\/p>\n<p><strong>Hide<\/strong><\/p>\n<p>To quote the documentation &#8220;Returns Enumerable sequence with the same behavior as the original, but hiding the source identity&#8221;.<\/p>\n<p>I&#8217;m not wholly sure of the use cases for this, but basically if we have the following<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nList&lt;int&gt; items = new List&lt;int&gt; { 3, 5, 6, 2, 76 };\r\n<\/pre>\n<p>if we used <em>items.AsEnumerable()<\/em> the type returned would still be a List however using<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar result = items.Hide();\r\n<\/pre>\n<p><em>result<\/em> will be a funky EnumerableEx type hiding the underlying implementation.<\/p>\n<p><strong>If<\/strong><\/p>\n<p>The If method is self-explanatory, it allows us to return an IEnumerable if a condition is met or it will return an empty sequence or the overload shown below acts as an if..else returning the alternate sequence<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nEnumerableEx.If(() =&gt; someCondition, new&#x5B;] { 3, 5, 6, 2, 76 }, new &#x5B;] {6, 7});\r\n<\/pre>\n<p>So it&#8217;s probably obvious that if the <em>someCondition<\/em> is true the first array is returned else the second array is returned.<\/p>\n<p><strong>IgnoreElements<\/strong><\/p>\n<p>A slightly odd one, which probably is more useful when used in combination with other methods. IgnoreElements returns a source sequence without its elements<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 5, 6, 2, 76 };\r\nvar result = items.IgnoreElements();\r\n<\/pre>\n<p>result will be an empty sequence.<\/p>\n<p><strong>IsEmpty<\/strong><\/p>\n<p>As the name suggests, checks if the sequence is empty or not, obviously the following is not empty<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 5, 6, 2, 76 };\r\nvar result = items.IsEmpty();\r\n<\/pre>\n<p>whereas the following will be empty<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 5, 6, 2, 76 };\r\nvar result = items.IgnoreElements().IsEmpty();\r\n<\/pre>\n<p><strong>Max<\/strong><\/p>\n<p>Returns the maximum value in the sequence<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 5, 6, 2, 76 };\r\nvar result = items.Max();\r\n<\/pre>\n<p>this will result in the <em>result<\/em> being 76.<\/p>\n<p><strong>MaxBy<\/strong><\/p>\n<p>In essence MaxBy returns a sequence of values less than the supplied comparer, for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 50, 6, 2, 76 };\r\nitems.MaxBy(i =&gt; i &lt; 50).ForEach(Console.WriteLine);\r\n<\/pre>\n<p>this will create a sequence with values less than 50 and in this case write them to the console, thus outputting the values 3, 6 and 2.<\/p>\n<p><strong>Memoize<\/strong><\/p>\n<p>Memoize creates a buffer over the source sequence to ensure that if we were to iterate over the items multiple times we would not call the source multiple times. Obviously this would be useful if we&#8217;ve got the data from some file system or remote source to stop us retrieving the data multiple times, in use we have<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 5, 6, 2, 76 };\r\nvar result = items.Memoize();\r\n<\/pre>\n<p><strong>Min<\/strong><\/p>\n<p>Returns the minimum value in the sequence<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 5, 6, 2, 76 };\r\nvar result = items.Max();\r\n<\/pre>\n<p>this will result in the <em>result<\/em> being 2.<\/p>\n<p><strong>MinBy<\/strong><\/p>\n<p>In essence MinBy returns a sequence of values greater than the supplied comparer, for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 50, 6, 2, 76 };\r\nitems.MinBy(i =&gt; i &lt; 50).ForEach(Console.WriteLine);\r\n<\/pre>\n<p>this will create a sequence with values greater or equal to 50 and in this case write them to the console, thus outputting the values 50 and 76.<\/p>\n<p><strong>OnErrorResumeNext<\/strong><\/p>\n<p>Concatenates the sequence with a second sequence regardless of whether an error occurred, used in situation where you might be getting data from a source that could fail, the example below just shows the syntax really as this wouldn&#8217;t need to use OnErrorResumeNext<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 50, 6, 2, 76 };\r\nvar result = items.OnErrorResumeNext(new&#x5B;] {9, 10});\r\n<\/pre>\n<p>result would contain the items sequence followed by the sequence { 9, 10 }.<\/p>\n<p><strong>Publish<\/strong><\/p>\n<p>To quote the documentation, &#8220;creates a buffer with a view over the source sequence, causing each enumerator to obtain access to the remainder of the sequence from the current index in the buffer&#8221;.<\/p>\n<p>This allows the sequence to be shared via the buffer, in syntax terms this looks like<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 50, 6, 2, 76 };\r\nvar buffer = items.Publish();\r\n<\/pre>\n<p>There is an overloaded method which allows you to supply a selector.<\/p>\n<p><strong>Repeat<\/strong><\/p>\n<p>Allows us to iterate through a sequence infinitely or with the overload, n times<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 5, 6, 2, 76 };\r\n\r\n\/\/ iterate over three times\r\nitems.Repeat(3).ForEach(Console.WriteLine);\r\n\r\n\/\/ iterate infinitely\r\nitems.Repeat().ForEach(Console.WriteLine);\r\n<\/pre>\n<p><strong>Retry<\/strong><\/p>\n<p>This method allows us to retry enumerating a sequence whilst an error occurs or via the overload we can specify the maximum number of retries<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nitems.Retry(2);\r\n<\/pre>\n<p><strong>Return<\/strong><\/p>\n<p>The Return method returns a single element as a sequence, for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nEnumerableEx.Return(1);\r\n<\/pre>\n<p>this creates an IEnumerable of integers with the single value 1 in it.<\/p>\n<p><strong>Scan<\/strong><\/p>\n<p>Scan generates a sequence using an accumulator, so for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 5, 6, 2, 76 };\r\nitems.Scan((i, j) =&gt; i + j).ForEach(Console.WriteLine);\r\n<\/pre>\n<p>will pass 3 (i) and 5 (j) into the accumulator method the result will be 8 this will then be pass into the accumulator as i followed by 6 (j) and so on.<\/p>\n<p><strong>SelectMany<\/strong><\/p>\n<p>Several overloads exist, the one shown here simply projects each element of the sequence with a given sequence. For example the following simply projects the array { 5, 6 } over the original sequence<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 50, 6, 2, 76 };\r\nitems.SelectMany(new &#x5B;] { 5, 6 }).ForEach(Console.WriteLine);\r\n<\/pre>\n<p>This will output { 5, 6 } the number of times matching the number of elements in the items sequence, i.e. 5 times.<\/p>\n<p><strong>Share<\/strong><\/p>\n<p>A couple of overloads. This method creates a buffer with a shared view over the sequence so mutiple enumerators can be used to fetch the next element from the sequence, this example is a little convoluted<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 20, 10, 60, 30 };\r\nitems.Share(x =&gt; x.Zip(x, (a, b) =&gt; a - b)).ForEach(Console.WriteLine);\r\n<\/pre>\n<p>The same sequence is used on Zip and passed into Zip hence we&#8217;re zipping the sequence with itself, the result selector simply subtracts one value from the other. When output to the console this will write a sequence 10, 30 because the first item (20) has the second item (10) subtracted from it, as then the next item (60) has the final item (30) subtracted.<\/p>\n<p><strong>SkipLast<\/strong><\/p>\n<p>Allows us to skip\/bypass n elements from the end of in the sequence, thus <\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 5, 6, 2, 76 };\r\nitems.SkipLast(2).ForEach(Console.WriteLine);\r\n<\/pre>\n<p>lists values 3, 5, 6 but not the last 2 items.<\/p>\n<p><strong>StartWith<\/strong><\/p>\n<p>StartWith starts the sequence with the newly supplied enumerable, for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 5, 6, 2, 76 };\r\nitems.StartWith(new &#x5B;]{9, 10}).ForEach(Console.WriteLine);\r\n<\/pre>\n<p>will output the sequence 9, 10 then follow with the items sequence.<\/p>\n<p><strong>TakeLast<\/strong><\/p>\n<p>In essence the opposite of SkipLast, TakeLast results in a sequence on the last n items, such as<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 5, 6, 2, 76 };\r\nitems.TakeLast(2).ForEach(Console.WriteLine);\r\n<\/pre>\n<p>which outputs 2 and 76.<\/p>\n<p><strong>Throw<\/strong><\/p>\n<p>With the Throw method we can create a sequence which throws an exception when we try to enumerate it, for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nEnumerableEx.Throw&lt;int&gt;(new NullReferenceException()).ForEach(Console.WriteLine);\r\n<\/pre>\n<p>will throw the NullReferenceException when ForEach attempts to enumerate the sequence.<\/p>\n<p><strong>Using<\/strong><\/p>\n<p>Using creates a sequence which has a resource who&#8217;s lifetime is determined by the sequence usage. The idea being the resource is created via the Using method&#8217;s first argument then passed to the second argument (in all likelihood to be used in some way) before an IEnumerable is returned. The key thing to note is the resource is not created until we use the returned IEnumerable, for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 5, 6 };\r\nIEnumerable&lt;int&gt; results = EnumerableEx.Using(() =&gt; new SomeDisposable(), resource =&gt; items);\r\nresults.ForEach(Console.WriteLine);\r\n<\/pre>\n<p>Assuming SomeDisposable implements IDisposable, when we call GetEnumerator the SomeDisposable is created and passed to the second argument &#8211; this rather simplistic example does nothing with the resource but hopefully you get the idea. We then return the IEnumerable and when the GetEnumerator completes the resources Dispose method is called.<\/p>\n<p><strong>While<\/strong><\/p>\n<p>Loops through the sequence whilst a condition is true, so for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nIEnumerable&lt;int&gt; items = new &#x5B;] { 3, 5, 6, 2, 76 };\r\n\r\nint i = 0;\r\nEnumerableEx.While(() =&gt; i++ &lt; 3, items).ForEach(Console.WriteLine);\r\n<\/pre>\n<p>will output the items sequence three times.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m a bit late to the party with this one &#8211; Ix or Interactive Extensions. Available on NuGet via the Ix-Main package. This will give us the System.Interactive assembly. Ix are basically a bunch of extension methods for IEnumerable and the EnumerableEx class. I&#8217;m sure many of us have written IEnumerable extensions to supply a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3],"tags":[],"class_list":["post-604","post","type-post","status-publish","format-standard","hentry","category-c"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/604","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=604"}],"version-history":[{"count":32,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/604\/revisions"}],"predecessor-version":[{"id":2325,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/604\/revisions\/2325"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=604"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=604"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=604"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}