Refactoring using statements with CodeRush/Refactor!

May 9th, 2012

As many of you know, the using statement is a good tool for managing types which will be accessing unmanaged resources. The using statement provides a simple and convenient syntax that ensures that objects that implement the IDisposable interface are correctly disposed.

To fix this, you can apply the automatic fix – the Introduce Using Statementcode provider:

The Introduce Using Statement code provider declares a using statement for the specified IDisposable implementer, removing the call to Dispose() if it exists. The code provider automatically detects and covers the required code into the using statement if applied on an undisposed variable, for example:

The refactoring preview hint helps you to see the refactored code, and the resulting code before applying it. If you wish to extend the code that must be placed inside the using statement, manually select it (including all required code):

Instead of the using statement, you can call the object’s Dispose method to indicate that you want the object to clean up its resources. However, in this case, you must make sure that the Dispose() call will always be executed by wrapping the entire code into the try/finally block. To do that, you can apply another refactoring that converts the selected using statement into a try/finally block – the Using to Try/Finally refactoring:

The result of the refactoring:

The Dispose() method will be called in the finally block even if an exception has been thrown during processing. But note that the scope of the variable is now changed. When the variable is declared inside of the using statement expression, the scope of the variable is the using statement and it is not visible outside of one. But after the statement is converted into a try/finally block, the scope of the variable will be increased, so it is visible to both try and finally blocks and the rest of the method (or parent block). This leads to the possibility that the object may be accidentally used again after control leaves the finally block even though the object probably no longer has access to its unmanaged resources. In other words, the object will no longer be fully initialized, and may cause an exception to be thrown if it is accessed. The Introduce Using Statement can fix this by converting try/finally block back to the using statement, so that the variable will remain in the scope of the using statement.

Both refactoring and code provider are the opposite of each other. You can refactor and improve the old code that uses the try/finally block or do the opposite – create a try/finally block for your advanced requirements.

The using statement may include multiple instances of the same type separated by a comma:

In this case these objects will both have the same scope. If you want to change the scope of one of the variables and write additional code, you can apply the Split Using Statement refactoring. The refactoring breaks the multi-declaration using statement into two or more neighboring using statements:

This refactoring has an opposite refactoring called the Consolidate Using Statements which combines several neighboring or nested using statements that cover variables of the same type into a single using statement:

All mentioned refactorings are available in both C# and Visual Basic languages if the specific language version supports the using statement.