Создал вот такой класс:
class CursorEx: IDisposable
{
public CursorEx()
{
Cursor.Current = Cursors.WaitCursor;
}
public void Dispose()
{
Cursor.Current = Cursors.Default;
}
}
Использую вот так:
public void Method()
{
new CursorEx();
//Здаесь что-то выполняется
}
Подразумевается, что после выполнения метода, вызовется метод Dispose() и курсор установится на дефолтный.
Могут ли быть какие-то варианты, когда произойдет сбой?
Ответ
Во-первых, вы забыли вызвать Dispose. Для этого следует использовать using
using (new CursorEx()) {
// что-то выполняется
}
На сборку мусора полагаться нельзя, она вызывается недетерминированно в любой момент после пропадания объекта из области видимости.
Во-вторых, вы не восстанавливаете исходный курсор. Если какая-то функция изменяет курсор, а затем вызывает функцию, которая тоже изменяет курсор, то курсор будет восстановлен уже после возврата из первой функции:
using (new CursorEx()) {
using (new CursorEx()) {
// что-то выполняется
}
// курсор уже восстановлен
}
// курсор должен был быть восстановлен здесь
Вам следует сохранять текущий курсор в конструкторе и восстанавливать его в Dispose
В-третьих, можно избавиться от лишнего объекта в памяти, если заменить класс на структуру.
Итого:
public struct CursorWaiter : IDisposable
{
private readonly Cursor _originalCursor;
public CursorWaiter (Cursor newCursor = null)
{
_originalCursor = Cursor.Current;
Cursor.Current = newCursor ?? Cursors.WaitCursor;
}
public void Dispose ()
{
Cursor.Current = _originalCursor;
}
}
Из комментариев: этот код рассчитан на то, что программист будет использовать тип только с помощью using, не будет уничтожать объект по несколько раз, не будет копировать и т.п. Если есть сомнения в этом, то нужно добавить проверку на повторный вызов Dispose (с помощью отдельного флага или обнуления _originalCursor), а также заменить класс на структуру для избавления он возможности копирования или вовсе скрыть тип за методом с лямбдой.
Комментариев нет:
Отправить комментарий