Sunday, December 27, 2009 1:12 AM bart

More LINQ with System.Interactive – Exceptional Exception Handling

With the recent release of the Reactive Extensions for .NET (Rx) on DevLabs, you’ll hear quite a bit about reactive programming, based on the IObservable<T> and IObserver<T> interfaces. A great amount of resources is available on Channel 9. In this series, I’ll focus on the dual of the System.Reactive assembly, which is System.Interactive, providing a bunch of extensions to the LINQ Standard Query Operators for IEnumerable<T>. In today’s installment we’ll talk about exception handling operators provided by EnumerableEx:

image

 

Iterating with and without exceptions

Under regular circumstances, one expects sequences to produce data in response to iteration. However, it’s perfectly possibly for an iterator (or any enumerable object) to throw an exception in response to a MoveNext call. For example:

Enumerable.Range(0, 10)
    .Reverse()
    .Select(x => 100 / x)
    .Run(Console.WriteLine);

This piece of code produces the following output:

11
12
14
16
20
25
33
50
100

Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero.
   at Demo.Program.<Main>b__0(Int32 x) in Program.cs:line 15
   at System.Linq.Enumerable.<>c__DisplayClass12`3.<CombineSelectors>b__11(TSource x)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.EnumerableEx.Run[TSource](IEnumerable`1 source)
   at Demo.Program.Main(String[] args) in Program.cs:line 13

Only when the Select operator’s iterator hits 0 for its input, its projection function will throw a DivideByZeroException, causing the iterator to come to an abrupt stop as seen above. In the connected world, where iterators may reach out to external services that can signal error conditions, the ability to handle such sequences in a better and composable way becomes increasingly important.

In this post, we’ll have a look at the exception handling primitives for enumerable sequences provided by Rx in System.Interactive.EnumerableEx. A related constructor operator, Throw, will be discussed later but is simply enough to reveal in this context because of its relevance:

var oops = EnumerableEx.Throw<int>(new Exception("Oops"));
oops.Run();

The Throw operator simply creates an iterator that throws the specified exception upon the first MoveNext call on its enumerator. It’s the counterpart to the Return operator creating a single-element iterator. Logically both correspond to the OnNext and OnError methods of IObserver<T> in the reactive world. In addition, we’ll see the relation between those operators and Notification<T> later on, when covering “Code = Data” discussing the Materialize and Dematerialize operators.

 

Catch it and move on

First on is the Catch operator which is available with the following signatures:

public static IEnumerable<TSource> Catch<TSource>(IEnumerable<IEnumerable<TSource>> sources);
public static IEnumerable<TSource> Catch<TSource, TException>(this IEnumerable<TSource> source, Func<TException, IEnumerable<TSource>> handler) where TException : Exception;

The second overload is the one used directly for exception handling as you’re used to it in your favorite imperative language. While you normally associate a handler code block with a “protected code block”, here a handler consists of a function producing a sequence in response to an exceptional iteration over the corresponding “protected sequence”. A sample will make things clearer. Consider the following iterator:

static IEnumerable<int> CouldThrow()
{
    yield return 1;
    yield return 2;
    throw new InvalidOperationException("Oops!");
}

Assume you can’t handle the exceptional condition from the inside and you got the iterator from somewhere else, so the following is impossible to achieve:

static IEnumerable<int> CouldThrow()
{
    try
    {
        yield return 1;
        yield return 2;
        throw new InvalidOperationException("Oops!");
    }
    catch (InvalidOperationException)
    {
        yield return 3;
        yield return 4;
        yield return 5;
    }
}

In fact, the above is invalid C# since you can’t yield from a try-block that’s associated with a catch clause, and neither can you yield from a catch clause. Either way, this illustrates basically what we want to achieve from a conceptual point of view, but on the consuming side of the iterator. This is what Catch allows us to do, as follows:

CouldThrow()
    .Catch((InvalidOperationException ex) => new[] { 3, 4, 5 })
    .Run(Console.WriteLine);

This simply prints the numbers 1 through 5 on the screen, where the last three values originate from the exception handler. Obviously one could inspect the exception object in the handler. Just like with regular block-based exception handling constructs, one can have multiple “nested” catch clauses associated with the same source sequence. This is achieved by simply chaining Catch operator calls:

new [] {
    /* yield return */ 1,
    /* yield return */ 2 }.Concat(
    /* throw */        EnumerableEx.Throw<int>(new InvalidOperationException("Oops!")))
.Catch((InvalidOperationException ex) => new [] {
    /* yield return */ 3,
    /* yield return */ 4 }.Concat(
    /* throw */        EnumerableEx.Throw<int>(new FormatException("Aargh!"))))
.Catch((FormatException ex) => new [] {
    /* yield return */ 5 })
.Run(Console.WriteLine);

Here, the first catch clause throws an exception by itself, being caught by the next catch clause. This is completely similar to regular exception handling. In summary, the Catch operator allows iteration of a sequence to continue with another one when an exception occurs during the first’s iteration. The handler function provided to Catch isn’t evaluated till an exception occurs, so if the resulting sequence isn’t iterated far enough for an exception to be triggered, the handler obviously won’t execute.

The second overload of Catch allows specifying a sequence of sequences (IEnumerable<IEnumerable<T>>), continuing a sequence that has terminated by an exception with the sequence following it. For example:

var ex = EnumerableEx.Throw<int>(new Exception());
EnumerableEx.Catch(new[]
    {
        new [] { 1, 2 }.Concat(ex),
        new [] { 3, 4 }.Concat(ex),
        new [] { 5 },
        new [] { 6 },
    }).Run(Console.WriteLine);

This again will print the numbers 1 through 5, but not 6. Reason is that the first sequence blew up after yielding 1 and 2, causing the next sequence yielding 3 and 4 to be looped in, again causing an exception followed by a hand-over to the third sequence yielding 5. This third sequence finishes regularly (as opposed to exceptionally), so the story ends. I leave it to the reader to write down the corresponding block-structured nested try-catch statements this corresponds to from a conceptual angle.

Exercise: how would you implement a rethrow operation?

image

 

Finally, too

Now we’ve seen the Catch operator, Finally should come as no surprise. From the signature alone, we can see what it does:

public static IEnumerable<TSource> Finally<TSource>(this IEnumerable<TSource> source, Action finallyAction);

Under whatever terminating circumstance when enumerating over the source, the finallyAction will be executed. Obviously this can be illustrated using two cases, one for the regular case and one for the exceptional case. For the latter, we use EnumerableEx.Throw again. First, the regular case:

/* try { */ new [] {
    /* yield return */ 1,
    /* yield return */ 2 }
.Finally(() =>
    Console.WriteLine("Finally"))
.Run(Console.WriteLine);

This will print 1 and 2, followed by the Finally message. In case of an exception, let’s show the similarity to the lexical nesting of exception handler blocks in C#:

/* try { */
    /* try { */ new[] {
        /* yield return */ 1,
        /* yield return */ 2 }.Concat(
        /* throw */        EnumerableEx.Throw<int>(new Exception()))
    .Finally(() =>
        Console.WriteLine("Finally"))
.Catch((Exception ex) => new[] {
    /* yield return */ 3,
    /* yield return */ 4,
    /* yield return */ 5 })
.Run(Console.WriteLine);

Here the innermost enumerable yields 1 and 2, followed by the throwing of an exception. The Finally operator ensures the printing action is executed no matter how this sequence terminates. In this case, the exception will be caught downstream by the Catch operator, so the end result on the screen will be 1, 2, Finally, 3, 4, 5. As a simple exercise, think about what the following code will and should print:

/* try { */
    /* try { */ new[] {
        /* yield return */ 1,
        /* yield return */ 2 }.Concat(
        /* throw */        EnumerableEx.Throw<int>(new Exception()))
    .Finally(() =>
        Console.WriteLine("Finally"))
.Catch((Exception ex) => new[] {
    /* yield return */ 3,
    /* yield return */ 4,
    /* yield return */ 5 })
.Take(2)
.Run(Console.WriteLine);

image 

(Note: break happens when a consumer stops iterating over the resulting sequence.)

 

OnErrorResumeNext as in VB

Visual Basic fans will recognize this operator without doubt. Its operation is fairly straightforward: given a sequence of sequences, those are enumerated one by one, yielding their result to the caller. This is pretty much the same as the Concat operator we’ll see when talking about combinators, with the main difference being that an exceptional termination of any of the sequences does not bubble up. Instead, the OnErrorResumeNext operator simply moves on to the next sequence it can “yield foreach”. A sample will make this clear, but first the signatures:

public static IEnumerable<TSource> OnErrorResumeNext<TSource>(params IEnumerable<TSource>[] sources);
public static IEnumerable<TSource> OnErrorResumeNext<TSource>(this IEnumerable<IEnumerable<TSource>> sources);
public static IEnumerable<TSource> OnErrorResumeNext<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> next);

The following sample prints numbers 1 through 9, with no exception surfacing, even though the third sequence did terminate exceptionally. Replacing the OnErrorResumeNext call with the use of the Concat operator would surface that exception, terminating the resulting sequence after 1 through 7 have been yielded:

EnumerableEx.OnErrorResumeNext(
    new [] { 1, 2 },
    new [] { 3, 4, 5 },
    new [] { 6, 7 }.Concat(EnumerableEx.Throw<int>(new Exception())),
    new [] { 8, 9 }
).Run(Console.WriteLine);

Use of this operator can be useful for batch processing of records where an exceptional return is tolerable.

image

 

Using resources

Just like C#’s and VB’s using statements are related to exceptions due to their “finally”-alike guarantees for cleanup, System.Interactive’s Using operator is used for proper resource cleanup, this time in the face of delayed execution of a sequence. The signature for Using is as follows:

public static IEnumerable<TSource> Using<TSource, TResource>(Func<TResource> resourceSelector, Func<TResource, IEnumerable<TSource>> resourceUsage) where TResource : IDisposable;

The idea is to create a sequence that acquires a resource when its iteration is started (by running resourceSelector), which is subsequently used to provide a data sequence “using the resource” (obtained through resourceUsage). It’s only when the resulting sequence terminates (exceptionally or regularly) that the resource is disposed by calling its Dispose method. To illustrate this, let’s cook up our own Action-based disposable:

class ActionDisposable : IDisposable
{
    private Action _a;

    public ActionDisposable(Action a)
    {
        _a = a;
    }

    public void Dispose()
    {
        _a();
    }
}

Now we can write the following two samples:

EnumerableEx.Using<int, ActionDisposable>(() => new ActionDisposable(() => Console.WriteLine("Gone")), a =>
{
    // Now we could be using a to get data back...
    Console.WriteLine(a is ActionDisposable);
    // ... but let's just return some stock data.
    return new[] { 1, 2, 3 };
})
.Run(Console.WriteLine);

EnumerableEx.Using<int, ActionDisposable>(() => new ActionDisposable(() => Console.WriteLine("Gone")), a =>
{
    // Now we could be using a to get data back...
    Console.WriteLine(a is ActionDisposable);
    // ... which may result in an exception.
    return new[] { 1, 2 }.Concat(EnumerableEx.Throw<int>(new Exception()));
})
.Catch((Exception ex) => new [] { 4, 5, 6 })
.Run(Console.WriteLine);

The first one will nicely obtain the Gone-printing resource when enumeration is triggered by Run, returning values 1, 2 and 3, before Using calls dispose on the resource, causing it to print “Gone”. In the second example, the results produced under the acquired resource scope trigger an exception, so upon leaving Using the resource will be disposed again (printing “Gone”), putting us in the Catch operator’s body as we saw before. Now the output will be 1, 2, Gone, 4, 5, 6. Again, as an exercise, think about the following one (easy, just stressing the point…):

EnumerableEx.Using<int, ActionDisposable>(() => new ActionDisposable(() => Console.WriteLine("Gone")), a =>
{
    // Now we could be using a to get data back...
    Console.WriteLine(a is ActionDisposable);
    // ... but let's just return some stock data.
    return new[] { 1, 2, 3 };
})
.Take(2)
.Run(Console.WriteLine);

image

(Note: break is caused by the consumer’s termination of iteration over the resulting sequence.)

 

Retry till you succeed

A final operator in the exception handling operators category we’re discussing in this post, is Retry. The idea of Retry is to retry enumerating and yielding a sequence till it terminates successfully:

public static IEnumerable<TValue> Retry<TValue>(this IEnumerable<TValue> source);
public static IEnumerable<TValue> Retry<TValue>(this IEnumerable<TValue> source, int retryCount);

Obviously, Retry has no effect if the source sequence iterates without an exception being triggered:

// A no-op.
new [] { 1, 2, 3 }
.Retry()
.Run(Console.WriteLine);

On the other hand, if an exception occurs, a new enumerator over the source sequence is obtained (using GetEnumerator) and iteration is retried. If the exception condition is persistent, this may cause infinite retry:

// Will go forever...
new [] { 1, 2, 3 }.Concat(EnumerableEx.Throw<int>(new Exception()))
.Retry()
.Run(Console.WriteLine);

The overload taking a retryCount can be used to cap the number of retries. If the exception condition is dependent on dynamic factors (e.g. network connectivity to a stream of data), use of Retry will eventually make the iteration succeed:

static int s_count = 0;
static IEnumerable<int> MayGetNumbers()
{
    try
    {
        yield return 4;
        if (s_count == 0)
            throw new Exception();
        yield return 5;
        if (s_count == 1)
            throw new Exception();
        yield return 6;
    }
    finally
    {
        s_count++;
    }
}

The iterator above will make a bit more progress every time it’s called, the first time getting stuck after yielding 4, the second time after yielding 4 and 5, and finally succeed to yield 4, 5 and 6. Using Retry on this one will produce the following result:

// 4, (!), 4, 5, (!), 4, 5, 6
MayGetNumbers()
.Retry()
.Run(Console.WriteLine);

I’ll leave it as an exercise to the reader to come up with a diagram for this operator, introducing a distinction between IEnumerable and IEnumerator, the latter being potentially different for every time the GetEnumerator method is called. It’s because of the potential different enumeration results that Retry has a chance to be effective.

 

Next on More LINQ

Constructor operators, producing (sometimes trivial) sequences.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under: ,

Comments

# re: More LINQ with System.Interactive – Exceptional Exception Handling

Sunday, December 27, 2009 1:39 AM by ControlFlow

Very nice post, thanks a lot!!!!

p.s. Last release of Rx contains generalized .Using() operator, with the type parameter, constrained to implement IDisposable. Maybe this is a reason to update a post...

# Twitted by thecryptic

Sunday, December 27, 2009 3:47 AM by Twitted by thecryptic

Pingback from  Twitted by thecryptic

# re: More LINQ with System.Interactive – Exceptional Exception Handling

Sunday, December 27, 2009 5:40 AM by Alexey Romanov

With Using, you will almost always actually use the resource, and not simply as an IDisposable, but with a more specific type, to which you have to cast it. So why don't you provide

public static IEnumerable<TSource, TResource> Using<TSource>(Func<TResource> resourceSelector, Func<TResource, IEnumerable<TSource>> resourceUsage) where TResource : IDisposable;

instead? (TResource should be inferrable from resourceSelector in most cases.)

# Twitter Trackbacks for More LINQ with System.Interactive ??? Exceptional Exception Handling - B# .NET Blog [bartdesmet.net] on Topsy.com

Pingback from  Twitter Trackbacks for                 More LINQ with System.Interactive ??? Exceptional Exception Handling - B# .NET Blog         [bartdesmet.net]        on Topsy.com

# re: More LINQ with System.Interactive – Exceptional Exception Handling

Sunday, December 27, 2009 8:41 AM by Parmenio

Great post.

One thing I noticed though is that the Using signature has changed in the latest build of Rx. The version of Rx I have lists it as

public static IEnumerable<TSource> Using<TSource, TResource>(Func<TResource> resourceSelector, Func<TResource, IEnumerable<TSource>> resourceUsage) where TResource: IDisposable

So in your example I had to change the code from EnumerableEx.Using<int> to EnumerableEx.Using<int,IDisposable> and then everything worked.

# re: More LINQ with System.Interactive – Exceptional Exception Handling

Sunday, December 27, 2009 9:27 AM by bart

Hi folks,

Yes, the Using operator has been updated in the last release. This post was based on earlier drops and I forgot to update the sample, so I did that now.

Thanks for letting me know,

-Bart

# Dew Drop &#8211; December 27, 2009 | Alvin Ashcraft&#039;s Morning Dew

Pingback from  Dew Drop &#8211; December 27, 2009 | Alvin Ashcraft&#039;s Morning Dew

# .NET System.Interactive and Monadic type systems

Monday, December 28, 2009 3:27 PM by .NET System.Interactive and Monadic type systems

Pingback from  .NET System.Interactive and Monadic type systems

# More LINQ with System.Interactive – Exploiting the code = data relationship

Tuesday, December 29, 2009 3:44 AM by B# .NET Blog

With the recent release of the Reactive Extensions for .NET (Rx) on DevLabs , you’ll hear quite a bit

# The Morning Brew - Chris Alcock &raquo; The Morning Brew #506

Tuesday, December 29, 2009 3:57 AM by The Morning Brew - Chris Alcock » The Morning Brew #506

Pingback from  The Morning Brew - Chris Alcock  &raquo; The Morning Brew #506

# Reactive Extensions for .NET (Rx) &laquo; Just Justin&#039;s

Saturday, February 06, 2010 3:45 AM by Reactive Extensions for .NET (Rx) « Just Justin's

Pingback from  Reactive Extensions for .NET (Rx)  &laquo; Just Justin&#039;s

# Introduction to the Reactive Extensions for JavaScript – Error Handling Part I

Tuesday, July 20, 2010 3:20 PM by Matthew Podwysocki

We’ve covered a bit recently with conditional and looping operators on the Reactive Extensions for JavaScript

# Introduction to the Reactive Extensions for JavaScript – Error Handling Part II

Monday, August 02, 2010 12:16 PM by Matthew Podwysocki

We’ve covered a bit recently with conditional and looping operators on the Reactive Extensions for JavaScript

# Introduction to the Reactive Extensions for JavaScript ??? Error Handling Part II | ImCoder.net

Pingback from  Introduction to the Reactive Extensions for JavaScript ??? Error Handling Part II | ImCoder.net

# Disposing sequence of resources with Reactive Extensions

Monday, June 13, 2011 2:46 PM by Chasing state of the art

Recall my previous post on Disposing sequence of resources where we were solving imperatively the following problems: Create single disposable representation for a sequence of disposable resources Defer resources allocation to avoid exception propagation