Click here to Skip to main content
Click here to Skip to main content

Tagged as

The "Using" Block as a Language Feature

, 5 Mar 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
Download source (55.5 KB)IntroductionThe "using" block in C# and VB.NET can be used as a high-level language construct, not just as a way of tidying-up. In this article I show you how to capture and restore state using constructors and disposers.BackgroundIn any substantial...

Introduction

 
The "using" block in C# and VB.NET can be used as a high-level language construct, not just as a way of tidying-up. In this article I show you how to capture and restore state using constructors and disposers.

Background

In any substantial application, especially those with a UI, it is frequently necessary to change state to perform some task and to then restore the state after - even if an error occurs. This usually involves a Try..Catch..Finally block and a lot of boilerplate code. If the implementation of the state changes then everywhere that captures and restores the state must be changed too. Think of simple things like capturing and restoring the selection in a combo box, or changing
the cursor to an hourglass and back again. A "nicer" approach would be to have some sort of language construct that surrounds the portion of code that occurs in the alternate state. In psuedocode such a construct might look like this:
    ...
    With(AlternateState)
    {
        // Do Stuff.
    }
    ...
The C# and VB.NET don't provide an easy way of adding language features like that, so the basis of the solution I have chosen is the "using" block (Using...End Using in VB.NET or using{...} in C#). In C# the usage is thus:
    using(System.IDisposable myObject = new MyDisposableType())
    {
        // Do stuff.
    }
This is equivalent to the following code:
    System.IDisposable myObject = new MyDisposableType();
    try
    {
        // Do stuff.
    }
    finally
    {
        if(myObject != null)
        {
            myObject.Dispose();
        }
    }
The only requirement to be able to use this construct is that the object used implements the System.IDisposable
interface. So, we have a constructor that is run at the start of the block and a Dispose method called at the end of the block. These provide the opportunity to capture and restore state respectively. If we are to fully implement the psuedocode example above then we also need to change state in the constructor, although I shan't be forcing that point.

Using the Code

In the code I provide implementations of three example cases:
 
ComboBoxState
  • Capture and restore the selected item in a combo box.
CursorState
  • Change and restore the cursor during an operation.
ImpersonateUser
  • Impersonate a user and restore the original user once the task is over.
The point of the three examples in the code is show how the state can be captured and changed in the constructor of the helper classes and then restored in the dispose method.
 
I have used all three (in rather artificial circumstances) in TestForm search for "EXAMPLE:" in the code to find them.

Points of Interest

So, what interesting points can we take from the first version of this demo code? Well, in the test form you can see a couple of simplistic methods for handling the setting of control properties from arbitrary threads - this shouldn't actually be a problem in this app. because the timer control raises events on form's main thread, but it is worth knowing about. There are probably some useful bits and pieces in the impersonation code too. This is quite old know and may contain work-arounds for bugs that no loner exists - I have included links back to the original articles to explain some of the more esoteric bits.
 
The main gotcha to watch out for though is unexpected changes in the state of objects prior to the dispose methods. Remember that the method may be called from an error handler or destructor and that controls or forms that have been captured in the constructor may have been disposed of themselves before you get to them. To combat this you need to code defensively and check properties such as IsHandleCreated.

History

Version 1.0
  • Initial version. It compiles and runs on my machine.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

open-collar
Web Developer
United Kingdom United Kingdom
.NET Developer based in London, UK.

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141223.1 | Last Updated 5 Mar 2010
Article Copyright 2010 by open-collar
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid