Scoped Values

Here's an interesting utility class, a scoped value. This allows you to have a member variable that gets changed for a time, and then automatically restored back to the original value.

Looked at another way, a Scoped is a member variable where changes are not permanent. Instead, changes are kept during a particular scope of execution, then reverted.

When is this useful?

One sample use is for the mouse cursor - with a suitably configured Scoped you can simply change the cursor to an hour glass during a process and then have it automatically restored again afterwards.

    using (screenCursor.As(Cursors.HourGlass))
    {
        // Long running action
    }

Contrast this with the code often written for this situation:

    Control.Cursor = Cursors.HourGlass;
    try
    {
        // Long running action
    }
    finally
    {
        Control.Cursor = Cursors.Default;
    }

One major issue with this code is that it doesn't support nesting - when this particular block completes, the cursor is restored to its default value, even if this block has been called as a part of processing a larger piece of work. Of course, this can be easily addressed by caching the existing value in a temporary variable, but this increases the amount of boilerplate code required.

Using a Scoped takes care of these details, leaving you to focus on the core logic that needs your attention.

Setup is relatively straightforward, just create a Scoped member variable and hook up a handler to the ValueChanged event.

Here's a full example ...

    public class ExampleForm : Form
    {
        public ExampleForm()
        {
            mScreenCursor = new Scoped<Cursor>(Cursors.Default);
            mScreenCursor.ValueChanged += UpdateCursor;
        }
 
        private void UpdateCursor(
            object sender,
            ValueChangedEventArgs<Cursor> args)
        {
            Cursor = args.Value;
        }
 
        private readonly Scoped<Cursor> mScreenCursor;
    }

AttachmentSize
Scoped<T> Source30.48 KB