Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yield return from a try/catch block [duplicate]

As Eric Lippert described in this article, yield return is not allowed within try/catch clauses.

Is there a nice way I could get something like this, without having to write my own IEnumerator by hand:

public IEnumerable<Data> GetData()
{
    var transaction = Session.BeginTransaction());
    try 
    {
        IQuery q = CreateQuery(session);

        foreach (var result in q.Enumerable())
            yield return ProjectResult(result);  // <-- doesn't work

        session.Commit();
    }
    catch (Exception ex)
    {
        transaction.Rollback();
        throw;
    }
    finally
    {
        transaction.Dispose();
    }
}
like image 610
Groo Avatar asked Aug 30 '11 14:08

Groo


People also ask

Is it good practice to return from catch block?

Yes, we can write a return statement of the method in catch and finally block. There is a situation where a method will have a return type and we can return some value at any part of the method based on the conditions.

What does a try catch return?

In a try-catch-finally block that has return statements, only the value from the finally block will be returned. When returning reference types, be aware of any updates being done on them in the finally block that could end up in unwanted results.

Why should I not wrap every block in try catch?

When you have methods that do multiple things you are multiplying the complexity, not adding it. In other words, a method that is wrapped in a try catch has two possible outcomes. You have the non-exception outcome and the exception outcome.

How do I return an item on try catch block?

Return your Dictionary end of your try block, return null from your catch . And every time you call this function check for returning value. If it's null then that means something bad happened. Because returning a null Dictionary is the same as returning null directly.


1 Answers

I'd just change the transaction-handling logic like this:

public IEnumerable<Data> GetData()
{
    var transaction = Session.BeginTransaction();
    bool rollback = true;
    try 
    {
        IQuery q = CreateQuery(session);

        foreach (var result in q.Enumerable())
        {
            yield return ProjectResult(result);
        }

        rollback = false;
        session.Commit();
    }
    finally
    {
        if (rollback)
        {
            transaction.Rollback();
        }
        transaction.Dispose();
    }
}

Or if your transaction supports the idea of "dispose means rollback unless it's commited":

public IEnumerable<Data> GetData()
{
    using (var transaction = Session.BeginTransaction();
    {
        IQuery q = CreateQuery(session);

        foreach (var result in q.Enumerable())
        {
            yield return ProjectResult(result);
        }

        // Commits the tnrasaction, so disposing it won't roll it back.
        session.Commit();
    }
}
like image 186
Jon Skeet Avatar answered Nov 03 '22 01:11

Jon Skeet