views:

191

answers:

7

What is an elegant way of writing this?

if (lastSelection != null)
{
    lastSelection.changeColor();
}
else
{
    MessageBox.Show("No Selection Made");
    return;
}

changeColor() is a void function and the function that is running the above code is a void function as well.

+8  A: 

Although I personally really dislike having multiple return statements in a function, according to the defensive programming I've seen, you'd trap the error condition and exit, and let anything else through:

if(lastSelection == null)
{
    MessageBox.Show("No Selection Made");
    return;
}

lastSelection.changeColor();

It's hard to say how I'd do this in my own work without seeing the entire function this belongs in.

overslacked
:-) Two minds entering the same solution at the same time. Yours has more commentary though.
Bevan
+13  A: 

You can reduce clutter by reversing the condition:

if (lastSelection == null)
{
    MessageBox.Show("No Selection Made");
    return;
}

lastSelection.changeColor();
Bevan
Ha! Well, +1 obviously :)
overslacked
+2  A: 

I'd be tempted to make sure that lastSelection was never null, and have it point to an "empty" object in cases where it would be null in the current design. Then, there's no need for a null check. Engineering possible errors out of the system is always good practice.

IOW, I'd ask if the inelegance in the code is how you do the null check, or whether it's the fact that a null check is required at all.

kyoryu
A "null" check may not be required, but this appears to be UI code, and it might be nice to tell the user "No Selection Made" if no selection has been made. In that case, even using the Null Object Pattern, it would be necessary to check for the null object in order to tell the user.
John Saunders
@John Saunders: And then I'd ask why the option to change color even existed if it was not a viable action - in that case, I'd prefer to block the action by disabling the control/whatever before it even got to this code. Alternately, the null object could trigger the message box to appear, directly or indirectly (ex: via an event on the object hooked up to the code in the UI that displays the box, to keep the null object unaware of the UI details).
kyoryu
@John Saunders: (BTW, it may be that there isn't a viable option to avoid the null check - but I'd certainly try to see if there was one).
kyoryu
@kyoryu: I don't understand. This may be a form used to do data entry for a new object. A new object might not have a default color, so the user has to select one. I suppose you could disable the "OK" button until a valid color was selected, but then how do you tell the user why the button is disabled?
John Saunders
@John Saunders: Given the fact that the object was called 'lastSelection', I kind of assumed it was more interactive. Without knowing the details more fully, it's really hard to say - we're both speculating here. And, as I've said, it may not be possible to avoid the null. My point is just that I would tend to prefer that solution, and try to achieve it if possible. I would also tend to design UI in such a way that invalid actions cannot be performed. These are obviously not achievable in all cases.
kyoryu
@John Saunders: IOW, if your point is that this may not be viable in all cases, *I agree.* I am simply saying that it is a pattern I would attempt to use in all cases where it *was* viable.
kyoryu
A: 

I think your code is good: you checked for the normal case (lastSelection != null) first then for the abnormal case.

I may just add a single modification:

if (lastSelection != null)
{
    lastSelection.changeColor();
    //your other normal code
}
else
{
    MessageBox.Show("No Selection Made");
    //return; //no need for this now
}
Sameh Serag
@Sameh: your suggestion works if that's all the code there is in the method. But how would you do it if there were 10 copies of the same code, perhaps with each one checking a different variable for null?
John Saunders
@John: this is a good point, but his problem seems simple enough to say what I have said.
Sameh Serag
@Sameh: it just seemed to me he didn't show us all his code, and that the code he showed wasn't the only code in the method. I could be wrong about that.
John Saunders
@Sameh: Except that he purposefully used only one return statement in which case it can be implied more code exists than is shown, in which case your answer might not be a safe bet. BTW, you don't need the curly braces in your example because comments are ignored.
John K
Error conditions must be checked first to avoid further scanning.
pokrate
@John and jdk: What you have said is good, but still his problem is simple (can overslacked tell us?). Ok, let's have another scenario: what if he has more than a single abnormal condition, each has a different reaction to take, wouldn't it be better to check the normal condition first?
Sameh Serag
@Sameh: Agreed about the normal condition but your answer does not satisfy the normal condition in the given code - see where the author chose to put the "early return" statement. It most logically follows that the other block doesn't hold to the same circumstances. Stated another way: why would the author have but a return statement in only one block if neither block continued processing after the condition?
John K
+1  A: 

Seeing everybody else got the good answers, DON'T do this:

if (lastSelection == null) goto ERR;
lastSelection.changeColor();
//... possibly more stuff...
return;
ERR:
MessageBox.Show("No Selection Made");
John K
Heh. This is good advice. Just to be clear, when I said I dislike multiple return statements, I didn't mean to advocate for gotos in any way!
overslacked
A: 

A practice catching up fast is to write null first as below :


if (null == lastSelection)
{
    MessageBox.Show("No Selection Made");
    return;
}

lastSelection.changeColor();

pokrate
@pokrate: "catching up fast"? Man, that's an artifact from back in the days of C, when the compiler wouldn't warn you about doing `if (lastSelection = null)`. That's nearly two decades old!
John Saunders
@pokrate, in case you didn't know, you'll actually get a *compiler error* if you try to assign a single variable in an if in c#. I'm so sad that these kinds of constructs will be all but lost....
overslacked
Thats a new practice, I have seen in almost all asp.net starter kits and here in StackOverflow. And I am using VS2008 and I cant see any compiler warning too.
pokrate
@overslacked: You are correct, *unless* the variable is of type bool. `if(bFoo = true)` will compile, and always execute the block.
kyoryu
"A practice catching up fast" - Somebody from the past has invented a time machine and visited StackOverflow! But all fun aside and to be fair, maybe this is catching on in the microcosm of your team, maybe a code style policy that has recently been allowed.
John K
A: 

This is yet another way of implementing this.

        Action _action = (lastSelection != null
                              ?
                                  new Action(lastSelection.changeColor)
                              :
                                  () => Console.WriteLine("No Selection Made"));
        _action.Invoke();

Perhaps a bit overkill, but you will certainly have the people maintaining your code scratching their heads :-)

DojoMojo
Reading this code made me itch, but the itch was not in my head :)
BillW
This code is very clever. Wait, something's wrong... I was *sure* that clever was a four-letter word...
kyoryu