-1

Looking at expression bodied methods, I am trying to understand why the return keyword is not used.

For example with

public int GetAge() { return this.Age; } 

I would have expected

public int GetAge() => return this.Age; 

as opposed to the correct

public int GetAge() => this.Age; 

Why is the return keyword not required/allowed in this case?

9
  • 2
    Why do you want to include the return keyword? There's nothing else that could be there, just the expression to return, so it's redundant. Commented Feb 11, 2021 at 21:31
  • 3
    Because this is the way this feature was designed =) And without this keyword code is much cleaner. Commented Feb 11, 2021 at 21:32
  • 1
    Ignoring void for a moment - by definition it ... consists of a single expression that returns a value whose type matches the method's return type ... And return as The return statement terminates execution of the method in which it appears and returns control to the calling method Therefore the return keyword is not used or required as the expression itself satisfies the function of the return statement. See stackoverflow.com/a/19224/426894 for differences between expression and statements. Commented Feb 11, 2021 at 21:32
  • 1
    It's there, they just spelled it like => instead to help people who golf in C# .. Of course, it's never gonna beat something like 05AB1E which takes "spell this operation differently" to another level ;) Commented Feb 11, 2021 at 21:38
  • 2
    You haven't explained why you expect a return to be in a context where an expression is expected. You just say you expect it without saying why, so it is hard to answer your "why not" question. What compelling user-focussed benefit do you see as justifying why a return should be required? If we can understand what language design principles you have in your head, that gives a good starting point for an answer to the question. Commented Feb 11, 2021 at 21:59

1 Answer 1

1

Expressions are short methods by convention. It's all about the delegation of a "thing" to do and what it takes to declare the contract: What you have and what you want in return.

It's pretty good to see in Lambdas: While you'll see this most of the time ...

 var tims = users.Where(u => u.Name.StartsWith("Tim")); 

... it is perfectly valid to write ...

 var tims = users.Where((User u) => u.Name.StartsWith("Tim")); 

... and even:

 var tims = users.Where((User u) => { return u.Name.StartsWith("Tim"); }); 

The latter is a full featured delegate syntax with arguments (User u) the curly braces for the method scope and the single-line body. In fact, this is quite the same method as this (except the lack of a method name):

 private bool IsTim(User u) { return u.Name.StartsWith("Tim"); } 

Which by the way would allow your lambda to look like this because IsTim() has exactly the same signature as the predicate for the Where-clause (= the lambda determining whether a user is a match or not).

 var tims = users.Where(IsTim); 

Skipping the last example, all of the other three lambda predicates do exactly the same thing but look pretty different:

 1 u => u.Name.StartsWith("Tim") 2 (User u) => u.Name.StartsWith("Tim") 3 (User u) => { return u.Name.StartsWith("Tim"); } 

Coming from case 3 to case 1 over the last years, the .NET team tried to minimize the keystrokes necessary to achieve the same thing. Delegates 3 have been there forever but with the introduction of Lambdas and Linq, Microsoft needed to simplify the delegating signature which led us to 2 and 1.

While case 2 is basically exact the same thing as case 3, case 1 is only valid in the correct context. It does not define the type of u but infers it in the context it is called. If you call this lambda on a list of users, u will be a user object. If you call it on a list of strings, it's representing a string (and won't compile in this case).

It took a while that Microsoft took over this logic to method and even property bodies but the logic is still the same: Why won't you reduce the necessary keystrokes if you can infer the arguments, return types and methods scopes by it's context?

That's why these two methods are exactly the same:

 private bool IsTim(User u) { return u.Name.StartsWith("Tim"); } private bool IsTim(User u) => u.Name.StartsWith("Tim"); 

u.Name.StartsWith("Tim") will always return a boolean value and the runtime already knows the arrow => to split the method arguments from the method body. It really is "pointing" to the expression producing the return value.

"Pointing to a return value" explains why there should not be a return keyword in public int GetAge() => this.Age;.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.