Автофлаг

Блокировка с использованием флагов используется часто, по причине тривиальной реализации и минимума используемых ресурсов. Необходимость сбрасывать флаг не только по выходу из блока но и в случае возникновения исключения вынуждает загромождать код блоками try/finally как показано ниже.

bool _uiLock;

try
{
   _uiLock = true
   //выполнение действий
}
finally
{
   _uiLock = false;
}

Реализация

Использование встроенной языковой конструкции using которая для объектов, реализующих интерфейс IDisposable, автоматически создает блок try/finally, а в блоке finally генерирует вызов метода Dispose, позволяет реализовать класс тривиальной блокировки, обеспечивающий более компактную форму записи.

using System;
using System.Diagnostics;

namespace IndustrialSoftware
{
   public class Flag
   {
     private bool _flag;

     public Flag()
     {}

     void IDisposable.Dispose()
     {
       _flag = false;
     }
     
     public bool Flagged
     {
      get { return _flag; }
     }
     
     public Flag Flag()
     {
      if (_flag)
      {
        Debug.Assert(false);
        throw new InvalidOperationException();
      }

      _flag = true;
      return this;
     }
     
     public static implicit operator bool(Flag f)
     {
      return f.Flagged;
     }
   }
}

Замечания по реализации

Интерфейс IDisposable реализован явно, что бы уменьшить вероятность вызова функции Dispose вне блока using. Неявное преобразование к bool позволяет использовать класс в логических выражениях.

Пример использования

Flag _uiLockFlag;

using (_uiLockFlag.Flag())
{
  //выполнение действий
}

//Неявное проверка флага выполняется так же, как и значение переменной типа bool
if(_uiLockFlag)
  return;