views:

338

answers:

14

I was reading through some C# code of mine today and found this line:

if (ProgenyList.ItemContainerGenerator.Status != System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated) return;

Notice that you can tell without scrolling that it's an "if" statement that works with ItemContainerGenerator.Status, but you can't easily tell that if the "if" clause evaluates to "true" the method will return at that point.

Realistically I should have moved the "return" statement to a line by itself, but it got me thinking about languages that allow the "then" part of the statement first. If C# permitted it, the line could look like this:

return if (ProgenyList.ItemContainerGenerator.Status != System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated);

This might be a bit "argumentative", but I'm wondering what people think about this kind of construct. It might serve to make lines like the one above more readable, but it also might be disastrous. Imagine this code:

return 3 if (x > y);

Logically we can only return if x > y, because there's no "else", but part of me looks at that and thinks, "are we still returning if x <= y? If so, what are we returning?"

What do you think of the "then before the if" construct? Does it exist in your language of choice? Do you use it often? Would C# benefit from it?

+3  A: 

It's look ugly for me. The existing syntax much better.

if (x > y) return 3;
Mendy
It only looks ugly because you're not used to it. Same thing when learning a new language. At first the grammar is weird, disconcerting, and just plain wrong. However, you get used to it and start thinking in that language and it makes more sense... Japanese is a good example: "Tomorrow red car with sunroof want to buy" that's a transliterated sentence. The verb is always ( pretty much ) the last thing you say. Which means you establish the parts of the phrase at the beginning, the subject, the object and then you join them together at the end. It's just different that's all. Same as this code
Atømix
Right. but things in any language are in one form, to prevent confusing. and if we let to write same statement both from the end the the beginning and from the beginning to the end, this will be very confusing, because you read something but you don't know immediately, if this is the beginning or the end.
Mendy
@Mendy, it's equally correct, and not confusing, in English to say "I will buy the red car if I have enough money" vs "If I have enough money I will buy the red car". Giving the programmer the option allows them to put more emphasis on what is important.
Jacob Stanley
+8  A: 

Yes. It reads better. Ruby has this as part of its syntax - the term being 'statement modifiers'

irb(main):001:0> puts "Yay Ruby!" if 2 == 2
Yay Ruby!
=> nil
irb(main):002:0> puts "Yay Ruby!" if 2 == 3
=> nil

To close, I need to stress that you need to 'use this with discretion'. The ruby idiom is to use this for one-liners. It can be abused - however I guess this falls into the realm of responsible development - don't constrain the better developers by building in restrictions to protect the poor ones.

Gishu
+8  A: 

I don't like the ambiguity this invites. Consider the following code:

doSomething(x)
if (x > y);
doSomethingElse(y);

What is it doing? Yes, the compiler could figure it out, but it would look pretty confusing for a programmer.

Evgeny
That's a great example of the ambiguity this could introduce. Perhaps if it was limited to "return" statements? I dunno.
Matt Hamilton
Where is the ambiguity? All you have done is inserted a new line.
liammclennan
I don't see the ambiguity. It's perfectly clear how this would be parsed.
Blindy
@liammclennan, @Blindy: The ambiguity is here. if(x>y); doSomethingElse(y); The programmer may tend to read it as if(x>y) doSomethingElse(y);
Veer
not at first glance. Whether `doSomething` or `doSomethingElse` is conditionally executed is only a matter of where that first semicolon is placed. It is easier to comprehend this as `doSomething(x); if(x>y){ doSomethingElse(y); }` so a developer might naturally read it as so and mess something up. Better to be clear.
Carson Myers
To clarify: I don't see it as ambiguity to the compiler, just to the human reader (if they don't pay close attention to the semicolons).
Matt Hamilton
Yea, not to mention that some languages <cough> Python </cough> don't treat the ';' a a line delimiter
Atømix
+1  A: 

I think Larry Wall was very smart when he put this feature into Perl. The idea is that you want to put the most important part at the beginning where it's easy to see. If you have a short statement (i.e. not a compound statement), you can put it before the if/while/etc. If you have a long (i.e. compound) statement, it goes in braces after the condition.

Gabe
A: 

Both Perl and Ruby have this and it works fine. Personally I'm fine with as much functionality you want to throw at me. The more choices I have to write my code the better the overall quality, right? "The right tool for the job" and all that.

Realistically though, it's kind of a moot point since it's pretty late for such a fundamental addition in C#'s lifecycle. We're at the point where any minor syntax change would take a lot of work to implement due to the size of the compiler code and its syntax parsing algorithm. For a new addition to be even considered it would have to bring quite a bit of functionality, and this is just a (not so) different way of saying the same thing.

Blindy
+3  A: 

I don't see any problem with

return 3 if (x > y);

It probably bothers you because you are not accustomed to the syntax. It is also nice to be able to say

return 3 unless y <= x

This is a nice syntax option, but I don't think that c# needs it.

liammclennan
Yes, Ruby allows the unless keyword. `return 'success!' unless errorCount > 0` as opposed to `return 'success' if errorCount < 1` It could be argued that the first statement is more clear.
Atømix
+12  A: 

Let's reformat that a bit and see:

using System.Windows.Controls.Primitives;

...

if (ProgenyList.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
{
    return;
}

Now how hard is it to see the return statement? Admittedly in SO you still need to scroll over to see the whole of the condition, but in an IDE you wouldn't have to... partly due to not trying to put the condition and the result on the same line, and party due to the using directive.

The benefit of the existing C# syntax is that the textual order reflects the execution order - if you want to know what will happen, you read the code from top to bottom.

Personally I'm not a fan of "return if..." - I'd rather reformat code for readability than change the ordering.

Jon Skeet
Well, with anonymous methods and lamdba expressions, textual order doesn't necessarily reflect execution order.
Senthil Kumar
@Senthil: True - but I think in that case the benefits outweigh the costs. In this situation I really don't think that's the case.
Jon Skeet
I don't like that it takes four lines of code to express such a simple concept.
Jacob Stanley
@Jacob if you prefer, that construct has an equivalent inline style, removing the curly braces, and placing the return after the end paren.
Jim Burger
@Jim of course, but then being able to put the return first is clearer imo.
Jacob Stanley
@Jacob and I would agree that a language should let you choose.
Jim Burger
@Jacob: You could remove the braces of course, to get it down to two lines - or possibly put the open brace on the same line as the "if" and the close brace on the same line as the "return".
Jon Skeet
I might be a bit biased on this because I've just discovered the feature in ruby (I'm a C# dev, but we're using rake for builds) and at the moment everything looks like a nail :P I like how it puts the important part (raise/return) in plain view, yet still only takes one line of code. Brilliant!
Jacob Stanley
@Jacob: Does this crop up sufficiently often in your code that using one line instead of two or four is actually an issue? I find the logic of test-then-execute is more important than putting everything on one line. Ultimately you need to understand both the action and the condition anyway, don't you?
Jon Skeet
@Jon: I like that the most important part is first. Seeing a return or a throw changes the context of what follows quite significantly. As for one line vs four, it's not that significant, but shorter is almost always better imo. I find that often C# presents me with far more text than required to describe a concept.
Jacob Stanley
+2  A: 

I think it's probably OK if the scope were limited to just return statements. As I said in my comment, imagine if this were allowed:

{
   doSomething();
   doSomethingElse();

   // 50 lines...

   lastThink();
} if (a < b);

But even just allowing it only on return statements is probably a slippery slope. People will ask, "return x if (a); is allowed, so why not something like doSomething() if (a);?" and then you're on your way down the slope :)

I know other languages do get away with it, but C#'s philosophy is more about making The One Right WayTM easy and having more than one way to do something is usually avoided (though with exceptions). Personally, I think it works pretty well, because I can look at someone else's code and know that it's pretty much in the same style that I'd write it in.

Dean Harding
`doSomething() if (a);` is perfectly fine. Your example however... probably couldn't be implemented. It would only be limited to single statement expressions.
Blindy
C# doesn't try for 'one right way'. I can think of at least 4 different ways to do conditionals in C#, 2 completely different LINQ syntaxes, 4 different ways to iterate, etc What is this slippery slope you speak of?
liammclennan
it looks like a `do/while` expression.
Carson Myers
`do/while` is different because you always execute the statement in the block at least once.
Dean Harding
A: 

It's considered grammatically incorrect to put the answer before the question, why would it be any different in code?

Doobi
Right, but this isn't putting the answer first, it's putting the ACTION first. "Buy eggs if we're out" isn't grammatically incorrect.
Blindy
I'll leave a rebuttal here if that's ok with you. :)
Matt Hamilton
A: 

Humans read beginning to end. In analyzing code flow, limits of the short term memory make it more difficult to read postfix conditions due to additional backtracking required. For short expressions, this may not be a problem, but for longer expressions it will incur significant overhead for users that are not seasoned in the language they are reading.

280Z28
It just takes getting used to it. Humans are remarkably adaptable. Look at Tagalog... `Na kay Tatay ang susi` transliterated is `At with Father the keys` translated is `"Father has the keys."` I'm sure Tagalog speakers would feel at home with `return x if <condition>`
Atømix
+1  A: 

Personally I like languages that let me choose.

That said, if you refactor as well as reformat, it probably doesn't matter what style you use, because they will be equally readable:

using System.Windows.Controls.Primitives;

...
var isContainersGenerated = 
    ProgenyList.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated;

if (!isContainersGenerated) return;
//alternatively

return if (!isContainersGenerated);
Jim Burger
A: 

Agreed with confusing , I never heard about this construction before , so I think correct way using then before if must always contents the result of else, like

return (x > y) ? 3 : null;

else way there is no point of using Imperative constructions like

return 3 if (x > y);
return 4 if (x = y);
return 5 if (x < y);

imho It's kinda weird, because I have no idea where to use it...

nCdy
+1  A: 

There is a concern reading the code that you think a statement will execute only later to find out it might execute.

For example if you read "doSomething(x)", you're thinking "okay so this calls doSomething(x)" but then you read the "if" after it and have to realise that the previous call is conditional on the if statement.

When the "if" is first you know immediately that the following code might happen and can treat it as such.

We tend to read sequentially, so reading and going in your mind "the following might happen" is a lot easier than reading and then realising everything you just read needs to be reparsed and that you need to evaluate everything to see if it's within the scope of your new if statement.

Graphain
A: 

It's like a lot of things really, it makes perfect sense when you use it in a limited context(a one liner), and makes absolutely no sense if you use it anywhere else.

The problem with that of course is that it'd be almost impossible to restrict the use to where it makes sense, and allowing its use where it doesn't make sense is just odd.

I know that there's a movement coming out of scripting languages to try and minimize the number of lines of code, but when you're talking about a compiled language, readability is really the key and as much as it might offend your sense of style, the 4 line model is clearer than the reversed if.

Chris