views:

76

answers:

2

Ok this might be a bit of hack but bear with me :) The background is that i'm tired of methods that that some if-statement to that messes up indention for the whole method, like:

public SomeClass DoStuff(string inputStr)
{
  SomeClass result =null;
  if (IsOpenFilter(inputStr))
  {
    ....
  }

  return result;
}

So I was thinking , wouldn't it be neat if I could do something like this instead:

public SomeClass DoStuff(string inputStr)
{
  Require(IsOpenFilter(inputStr),null);


  ....

  return result;
}

This case might be covered by code contracts in some form, if so please correct me :)

The idea is that if the statement does not evaluates to true it would return null. If there wasn't a return type for the method it would simply be: Require(IsOpenFilter(inputStr));

So I guess there's two questions, can this be done somehow? I'm stumped on how to do a conditional return from calling a method.

The other question is, is this a good idea? It's a bit weird to monkeypatch the language like this but I'd rather like the way the code reads. I would be even cleaner if it could be put into an attribute above the method: [Require(IsOpenFilter(inputStr))]

+3  A: 

What about rewriting your first example like this:

public SomeClass DoStuff(string inputStr) 
{ 
  if (!IsOpenFilter(inputStr)) 
      return null;

  SomeClass result =null; 

  // Some code .... 

  return result; 
} 

It looks like you are trying to stick to the old convention of one return point in each function. To make it short: Having one return is a heritage from languages with explicit resource handling. The long story is available in some old SO posts:

Anders Abel
Yeah, it's an old habit that perhaps I should break, it feels tough though to break *two* of my rules, if-statements without brackets and always put the return statement last :) Would be cleaner if there was some basic Require syntax I could use instead
MattiasK
You can of course still use braces with the if statement. The other point, to have a single return is something that belongs to C and other "older" (or low-level) languages.
Anders Abel
Yah, but that's too verbose :) I guess the criteria is brevity as well as indentiation
MattiasK
@Mattias: The if statement with braces is the best way to go here, IMO. If you want to reduce the line count, you could always go for "brace at the end" :)
Jon Skeet
+2  A: 

I agree with Anders: invert the condition and return early. "Single return point" used to be valuable when you needed to explicitly do a bunch of resource clean-up at that return point; with finally blocks, using statements and garbage collection it's not even a useful guideline any more, IMO. Any time you find yourself doing something just to get a single return point, consider whether it's actually making the code more readable.

I almost always find that if at some point in the code I know the return value and there are no other actions I want to take within the method, the best thing is to return immediately. Forcing readers to look through the rest of the method just in case there's another action is neither elegant nor useful, IMO.

I think it's a good thing that a method can't indicate that it should cause the caller to return - that ability sounds like a readability nightmare. Having said that, I have considered a new sort of conditional return statement:

return? expression;

This would return the evaluateed value of expression if it's non-null; you could use it for non-nullable types like this:

int Foo()
{
    return? Bar(); // Where Bar() has a return type of int?
    ...
}

Basically it would be the return statement equivalent of the null-coalescing operator.

This wouldn't help in your case, mind you - you want to return null early...

Jon Skeet
I dunno, as an attribute I think it would be quite readable and IMO cleaner than the other if-based approaches. If not possible I agree that the early if-statement is the way to go. I guess another way to go was to have some code-generation step the rewrites the syntax into an normal if-statement before compiling, but that might be a little overkill even if you could do some cool stuff that way new programmers would be a bit stumped :)
MattiasK
@Mattias: When reading the *calling* code, it wouldn't be obvious what's going on at all. You wouldn't see the attribute... how would you know that it would return? Remember that simple usually trumps clever.
Jon Skeet
If you read just the calling code how would you ever know exactly what the method would return, you'd only know the signature and return type and this wouldnt affect that...
MattiasK
@Mattias: But it would affect the behaviour of your calling code, in terms of unexpectedly returning for your method. I shouldn't have to check every method I call to see whether or not it will suddenly return (without throwing an exception). Compare how often you'd really want this with the relatively small additional cruft of the extra "if" block. Aside from anything else, you'd only be able to use it if *all* callers would want that behaviour. What if I wanted to call the method but then log the result before returning it, for example?
Jon Skeet
If a method *must* meet some criteria code contracts would be the way to go. This is for situations where some input is accepted but you'd want to return directly (possibly with value) if some condition(s) weren't met. You wouldn't have to check every method, it would be a black box exactly as before.Personally I have lots of these kind of if-statements that only serves to "bulletproof" methods and going from three lines to one (or two if you skip the brackets), and skipping the indentation would be great for readability.Guess it comes down to whether it's worth it and personal taste :)
MattiasK
@Mattias: It's not a black box, because the method would behave very strangely. When I call a method, I want to know how it's going to behave - I wouldn't expect it to return from *my* method except with an exception... so if it *could* do so, I'd have to check each method I call to see if it's got this bizarre behaviour.
Jon Skeet
I think we might be talking about different things these two lines would be identical:Require(IsOpenFilter(inputStr),"return string"));andif (!IsOpenFilter(inputStr)){ return "return string";}orRequire(IsOpenFilter(inputStr));and if (!IsOpenFilter(inputStr)) return:It wouldnt exit the calling method from itself, just from the actual method it's in. Regarding the headline that was more on *how* it would be implemented
MattiasK
@Mattias: It's still making a method call return automatically when there's no indication from the calling code that that will be the case. I wouldn't expect a simple method call to return from the calling method other than via an exception. Again, if this became a possibility it would mean I'd have to check every method call to see whether it was going to behave in this weird way. Sorry, but I can't see how that makes the code *clearer* at all.
Jon Skeet
It's just a shortcut syntax to write a conditional return, I guess if someone didn't know that it would be confusing, but I have a hard time seeing it would impact your code otherwise. I guess another more clear syntax could be: "return? IsOpenFilter() : null;"
MattiasK
@Mattias: Exactly - if you don't know whether it's going to do it or not, it's confusing... and there's no indication that it will do it from the method call. Something involving "return?" or whatever would be preferable, yes.
Jon Skeet
Ok then, I agree that a new keyword like that would be best, I was just wondering if it was possible to implement yourself with calling a method somehow, but, perhaps luckily, I don't it is :)Anyways, it would be a neat little feature :) and thanks for the discussion
MattiasK