views:

125

answers:

5

I am programming in C#.NET. It is possible to abort the set procedure of a class property without throwing an exception?

Here is what I want to do...

public int RandomProperty
{
    set
    {
     DialogResult answer = new DialogResult();
     answer = MessageBox.Show("This process could take up to 5 min. Are you sure you want to continue?");
     if(answer = DialogResult.No) 
        CancelSet   // Can I do something similar here?
     else
     {
      ...Do set procedure
     }
    }
}

I don't think I can use a method (instead of a property) because I am setting this value with a propertygrid.

+1  A: 

Just return out of the set. You'll have to use a private field to hold the value of what you want to set, but returning in the "cancel" should do it.

Joel Etherton
+12  A: 

IMO that is simply not a good thing to do - the expectation is that if the set doesn't throw it assigned the value. Test in the UI (or where-ever) before doing the set, or throw and handle an exception. Alternatively, the caller might be less confused by a method:

public bool TrySetRandomProperty(SomeType value) {
    ...
}

which returns true or false to indicate whether it happened. You should also avoid bleeding UI code into domain logic; perhaps use an event to let the UI talk to the user without inflicting a particular UI implementation on the caller?

Marc Gravell
+3  A: 

Ugh. Do you really want to involve the user interface inside a class property? Shouldn't you do this check further out in the user interface?

Pontus Gagge
+2  A: 

You can certainly code it this way, just don't set the field.

However, you've got a very bad design as you are mixing UI into your low-level code.

Asking the question before setting the property is a one option.

ChrisF
+6  A: 

Under no circumstances should you do any of this. A property should always be fast and logically represent a property of something. Ideally it should never fail. It certainly should not produce side effects such as popping up UI. You're violating all of these important guidelines. Don't do it.

Furthermore, your UI design is bad. Don't ask a user beforehand "this might take a while, are you sure?" and then punish them with a long wait if they click yes. Instead, start the operation, and if it doesn't return quickly, pop up a UI element that shows a progress bar and an estimated time left that has a cancel button.

You should probably write your long-running operation as an asynchronous method that can be cleanly cancelled on another thread.

A good architecture for this sort of thing is to have your method return immediately an object that exposes events like "I'm still running and here's how far along I am", or "I'm done now and here's the result", or "I got an error while attempting to do the operation and here's what it is". That object can also expose a "cancel" method that knows how to communicate with the worker thread and shut it down cleanly. The caller of the method that gets this object can then decide how to display the UI to the user.

With this architecture you separate your UI logic, your asynchrony logic and your business process logic from each other cleanly. This is work, but it pays dividends later.

Eric Lippert