Try/finally or local variable



  • Lately I have seen a (IMO) minor WTF posted in a Java newsgroup as an example, and I'd like to hear your opinions about it.



    The problem was that a method had to return a value and also set the
    field that contains that value to null. Now I would write code like
    this:



    Object someMethod() {

        Object retval = someField;

        someField = null;

        return retval;

    }



    Posted in the newsgroup I found code like this:



    Object someMethod() {

        try {

            return someField;

        } finally {

            someField = null;

        }

    }



    Now, I think (ab-)using try/finally for this is a bad thing to do. If
    you look in the bytecode, you will see that the try/finally example
    produces about two times the bytecode that the first example produces
    and of course half of that code is unreachable. Also it does not save
    any stack space, because the try/finally just creates an anonymous
    local variable to save the result to be returned through the execution
    of the finally code, so the only thing to save is creativity in naming
    the temporary variable, which is, why I always use the name "retval" in
    such circumstances.



    Maybe the author of the try/finally example thought it is more
    readable, but I don't think so. While I think every programmer should
    be familiar how try/catch/finally works, the previous thread "Try
    without Catch" shows clearly, that this cannot be expected, hence the
    explicit version with a local variable will be understood by a larger
    group of programmers than the try/finally version.



    Did I miss something? Is there any good reason to use try/finally, that I have failed to mention in this post?



    cu



  • FWIW, I agree with you.



  • Yeech, a try without an except/catch? Bad. Bad.

    Try is to catch exceptions, right? I think someone got carried away with "finally"



  • @Cyresse said:

    Yeech, a try without an except/catch? Bad. Bad.

    Try is to catch exceptions, right? I think someone got carried away with "finally"


    It's a perfectly accepted and standard practice to use try/finally as a means of guarunteed execution.  The C# using keyword is just syntactic sugar around a try/finally construct.

    I will agree that try/finally shouldn't be used for such a thing. Introducing a try/finally construct to this simple operation increases the structural complexity considerably.


  • @Cyresse said:

    Yeech, a try without an except/catch? Bad. Bad.

    Try is to catch exceptions, right? I think someone got carried away with "finally"



    No, it makes sense in languages that don't have deterministic destruction (rsp. "disposal" as in C#).



  • with the following snippet:



            private void button1_Click(object sender, System.EventArgs e)

            {

                string value = GetValue();

                MessageBox.Show(value);

                DataTable table = GetTable();

                MessageBox.Show(table.TableName);

            }



            public string GetValue()

            {

                string value = "test";

                try

                {

                    return value;

                }

                finally

                {

                    value = "no test";

                }

            }



            public DataTable GetTable()

            {

                DataTable table = new DataTable("MyTable");

                try

                {

                    return table;

                }

                finally

                {

                    table.TableName = "MyOtherTable";

                }

            }



    In C#, for value types, the finally statement has no impact. But for
    reference types, the finally statement does have an impact (since the
    objects are on the heap)



    Hence:

    The first message box will be "Test"

    The second message box will be "MyOtherTable"



    Either way, such code can be confusing and have unexpected results and really is to be avoided at all costs.







  • @b1xml2 said:

    with the following snippet:



            private void button1_Click(object sender, System.EventArgs e)

            {

                string value = GetValue();

                MessageBox.Show(value);

                DataTable table = GetTable();

                MessageBox.Show(table.TableName);

            }



            public string GetValue()

            {

                string value = "test";

                try

                {

                    return value;

                }

                finally

                {

                    value = "no test";

                }

            }



            public DataTable GetTable()

            {

                DataTable table = new DataTable("MyTable");

                try

                {

                    return table;

                }

                finally

                {

                    table.TableName = "MyOtherTable";

                }

            }



    In C#, for value types, the finally statement has no impact. But for
    reference types, the finally statement does have an impact (since the
    objects are on the heap)



    Hence:

    The first message box will be "Test"

    The second message box will be "MyOtherTable"



    Either way, such code can be confusing and have unexpected results and really is to be avoided at all costs.









    I would like to correct myself. The unexpected behaviour applies to
    strings only and not to other value types such as integers. Nonetheless
    it is rather interesting to say the least to see such unexpected
    results.



  • ignore my last post...it has been a tiring day =)



  • @b1xml2 said:

    ignore my last post...it has been a tiring day =)

    Ok, because otherwise I would point out that your code would'nt even compile, because your return the wrong type!



  • @Alexis de Torquemada said:

    @Cyresse said:
    Yeech, a try without an except/catch? Bad. Bad.

    Try is to catch exceptions, right? I think someone got carried away with "finally"



    No, it makes sense in languages that don't have deterministic destruction (rsp. "disposal" as in C#).

    Yes, but this is in Java and not some other language.  In Java, the only reason to use a try/finally is to guarantee code is executed [i]in the face of an exception[/i] regardless of how that exception is handled.  The posted code had nothing to do with an exception and was a good example of abusing try/finally.

    I wouldn't say try is for catching exceptiosn, however, as it's entirely possible you don't want to catch the exception but you do want to guarantee code is executed despite one.  A classic example is

    <FONT face="Courier New">try {</FONT>

    <FONT face="Courier New">    lock.lock();</FONT>

    <FONT face="Courier New">} finally {</FONT>

    <FONT face="Courier New">    lock.unlock();</FONT>

    <FONT face="Courier New">}</FONT>

    without which an unchecked exception would cause the lock to never be released.


Log in to reply