not a name
not a name

Reputation: 33

Pattern for cancel methods in a class

public class Foo : Collection<string>
{
  bool _cancel = false;
  public void AddWithoutDoingStuff(string item)
  {
    _cancel = true;
    Add(item);
    _cancel = false;
  }
  protected override void InsertItem(int index, string item)
  {
    base.InsertItem(index, item);
    if (!_cancel)
    {
      //Do some stuff
    }
  }
}

I wonder if there is a pattern to avoid this ugly _cancel member? I found something here: Temporarily stop form events from either being raised or being handled? But this only works with events.

Edit Sorry I did not express myself well. This is just a example. The explicit base class doesn't matter. What I'm want to ask for is a general solution to avoid the _cancel variable in this case. I don't like the method AddWithoutDoingStuff as it is in this example. It is not save in case of errors, so I have to do something like that:

try
{
  _cancel = true;
  Add(item);
}
finally
{
  _cancel = false;
}

It is also not threat save.

Upvotes: 3

Views: 104

Answers (2)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236228

You cannot override the way Add method works. And it just calls InsertItem without any additional parameters. That mean the only way to have some additional parameters inside InserItem is passing them via class fields (your solution).

But if you will not call base Add method you can control what is done or not done before/after inserting item

public class Foo : Collection<string>
{
    public void AddWithoutDoingStuff(string item)
    {
        if (Items.IsReadOnly())
           throw new NotSupportedException();

        base.InsertItem(Count, item);
    }

    protected override void InsertItem(int index, string item)
    {
        base.InsertItem(index, item);
        // Do Some Stuff
    }
}

NOTE: Unfortunately checking whether internal Items is readonly done in Add method of base class. And there is no verification in InsertItem method. So it would be nice if you'll do same check.

Upvotes: 1

CDove
CDove

Reputation: 1950

Your Collection object has no need for nor should it have a _cancel bool, especially since we're talking Forms.

If by Forms you mean WinForms, and as we're event driven here I presume you do, then the proper way to handle this would be to retrieve any cancellation as a parameter from the UI or calling method and resolve it before ever calling the collection. It's better to just not execute a process than execute one and cancel it. Example (undeclared variables are assumed further up the code):

DialogResult dr = MessageBox.Show("Do this?", "Question", MessageButton.OKCancel);
myFoo.InsertItem(myIndex, myItem, (r != DialogResult.Cancel ? true : false);

And of course you'd modify your InsertItem method slightly:

  protected void InsertItem(int index, string item, bool _cancel)
  {
    base.InsertItem(index, item);
    if (!_cancel)
    {
      //Do some stuff
    }
  }

It doesn't have to be a MessageBox. I just used that to illustrate the proper way to manage your toggle without having that ugly _cancel field in your class.

Also, along the thread of one of the comments now that I'm caffeinating, you should have a collection as a part of the class, notsomuch inherit from Collection.

Upvotes: 0

Related Questions