-
Notifications
You must be signed in to change notification settings - Fork 6k
Revisions to lambda expressions topic. #1285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
❌ Validation status: errorsdocs/csharp/lambda-expressions.md
For more details, please refer to the build report. Note: If you changed an existing file name or deleted a file, broken links in other files to the deleted or renamed file are listed only in the full build report. |
There are some build errors. It would be good to fix those first, otherwise we can't even see it on staging. |
@mairaw I think I've fixed all the build errors. A new build should run shortly. |
✅ Validation status: passed
For more details, please refer to the build report. Note: If you changed an existing file name or deleted a file, broken links in other files to the deleted or renamed file are listed only in the full build report. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good - add a few minor comments.
keywords: .NET, .NET Core | ||
author: dotnet-bot | ||
manager: wpickett | ||
ms.date: 06/20/2016 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update the date; also needs a ms.author.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stevehoag Thanks. I completely forgot to copy the header from the original topic.
|
||
## Lambda expressions and tuples ## | ||
|
||
Starting with C# 7.0, the C# language provides built-in support for tuples. You can provide a tuple as an argument to a lambda expression, and your lambda expression can also return a tuple. In some cases, the C# compiler uses type inference to determine the types of tuple components. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Link to the Tuples topic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stevehoag I've added it. Thanks for thinking of it; I'd intended to do it, and forgot
|
||
[!CODE [csSnippets.Lambdas](../../samples/snippets/csharp/concepts/lambda-expressions/query1.cs#3)] | ||
|
||
You can also supply a lambda expression when the argument type is an @System.Linq.Expressions.Expression%601, for example in the standard query operators that are defined in the @System.Linq.Queryable type. When you specify an @System.Linq.Expressions.Expression%601 argument, the lambda is compiled to an expression tree. The following example uses the @System.Linq.Enumerable.Count%60%601(System.Collections.Generic.IEnumerable{t%60%600})) standard query operator. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last link (@System.Linq.Enumerable.Count) isn't resolving.
|
||
## See Also ## | ||
|
||
[LINQ (Language-Integrated Query)](../standard/using-linq.md) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These three links are all showing up on a single line - was that intentional?
|
||
- A lambda expression cannot contain a `goto` statement, `break` statement, or `continue` statement that is inside the lambda function if the jump statement’s target is outside the block. It is also an error to have a jump statement outside the lambda function block if the target is inside the block. | ||
|
||
## Featured Book Chapter ## |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we still be linking to this? The book was published in 2007.
✅ Validation status: passed
For more details, please refer to the build report. Note: If you changed an existing file name or deleted a file, broken links in other files to the deleted or renamed file are listed only in the full build report. |
|
||
[!CODE [csSnippets.Lambdas](../../samples/snippets/csharp/concepts/lambda-expressions/infer1.cs#1)] | ||
|
||
The general rules for type inteference for lambdas are: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: inteference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mairaw And I didn't even spell the wrong word (interference) correctly. Fixed.
|
||
## Variable Scope in Lambda Expressions ## | ||
|
||
Lambdas can refer to *outer variables* (see [Anonymous methods](programming-guide/statements-expressions-operators/anonymous-methods.md)) that are in scope in the method that defines the lambda function, or in scope in the type that contains the lambda expression. Variables that are captured in this manner are stored for use in the lambda expression even if the variables would otherwise go out of scope and be garbage collected. An outer variable must be definitely assigned before it can be consumed in a lambda expression. The following example demonstrates these rules. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
must be definitely -> must be (I think the must is enough)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this should stay "definitely assigned". That's the phrase the spec always uses for the analysis of assignment to a variable before it is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good to know @BillWagner 😄
|
||
## Type inference in lambda expressions ## | ||
|
||
When writing lambdas, you often do not have to specify a type for the input parameters because the compiler can infer the type based on the lambda body, the parameter’s delegate type, and other factors, as described in the C# Language Specification. For most of the standard query operators, the first input is the type of the elements in the source sequence. So if you are querying an `IEnumerable<Customer>`, then the input variable is inferred to be a `Customer` object, which means you have access to its methods and properties: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: missing comma after So
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd just remove "So".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should delete "delegate" in the phrase "the parameter's delegate type". Or am I misunderstanding this sentence?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mairaw @BillWagner I've removed the "So". And changed "the parameter's delegate type" to "the parameter types".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ron, I like the way you've explained all the concepts here.
I had a few locations where the language is technically incorrect based on the terms used in the spec. once those are handled, this looks great.
ms.assetid: b6a0539a-8ce5-4da7-adcf-44be345a2714 | ||
-title: Lambda Expressions | ||
-description: Lean to use lambda expressions, which are executable code blocks that can be passed as arguments. | ||
-keywords: .NET, .NET Core, lambda epxressions, lambdas, delegates |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: epxressions
|
||
- Creating [expression trees](expression-trees-building.md). | ||
|
||
Lambda expressions are delegates. The specific delegate type of a lambda expressions depends on its parameters and return value. Lambda expressions that don't return a value correspond to a specific `Action` delegate, depending on its number of parameters. Lambda expressions that return a value correspond to a specific `Func` delegate, depending on its number of parameters. For example, a lambda expression that has two parameters but returns no value corresponds to an @System.Action%602 delegate. A lambda expression that has one parameter and returns a value corresponds to @System.Func%602 delegate. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lambda expressions are delegates, except when they are expression trees.
Maybe "Lambda expressions are code that can be represented either as a delegate, or an expression tree that would compile to a delegate". (I'm not sure I like that wording, improve at will.)
|
||
[!CODE [csSnippets.Lambdas](../../samples/snippets/csharp/concepts/lambda-expressions/expression3.cs#3)] | ||
|
||
Note in the previous example that the body of an expression lambda can consist of a method call. However, if you are creating expression trees that are evaluated outside of the .NET Framework, such as in SQL Server, you should not use method calls in lambda expressions. The methods will have no meaning outside the context of the .NET runtime. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add some weasel words here. Entity Framework does translate some known methods (especially on the string class. The guidance is correct in the general case.
|
||
[!CODE [csSnippets.Lambdas](../../samples/snippets/csharp/concepts/lambda-expressions/statement1.cs#1)] | ||
|
||
Statement lambdas, like anonymous methods, cannot be used to create expression trees. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd recommend deleting "like anonymous methods". The C# spec defines lambda expressions as a syntax for anonymous methods, so in that sense all lambda expressions are anonymous methods.
|
||
## Lambdas with the standard query operators ## | ||
|
||
Many standard query operators have an input parameter whose type is one of the @System.Func%601 family of generic delegates. These delegates use type parameters to define the number and type of input parameters, and the return type of the delegate. `Func` delegates are very useful for encapsulating user-defined expressions that are applied to each element in a set of source data. For example, consider the @System.Func%601 delegate, whose syntax is: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would start this by saying "LINQ to Objects, among other implementations" have an input parameter..
That way this is distinguished from the IQueryable discussion later.
|
||
## Type inference in lambda expressions ## | ||
|
||
When writing lambdas, you often do not have to specify a type for the input parameters because the compiler can infer the type based on the lambda body, the parameter’s delegate type, and other factors, as described in the C# Language Specification. For most of the standard query operators, the first input is the type of the elements in the source sequence. So if you are querying an `IEnumerable<Customer>`, then the input variable is inferred to be a `Customer` object, which means you have access to its methods and properties: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd just remove "So".
|
||
## Type inference in lambda expressions ## | ||
|
||
When writing lambdas, you often do not have to specify a type for the input parameters because the compiler can infer the type based on the lambda body, the parameter’s delegate type, and other factors, as described in the C# Language Specification. For most of the standard query operators, the first input is the type of the elements in the source sequence. So if you are querying an `IEnumerable<Customer>`, then the input variable is inferred to be a `Customer` object, which means you have access to its methods and properties: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should delete "delegate" in the phrase "the parameter's delegate type". Or am I misunderstanding this sentence?
|
||
## Variable Scope in Lambda Expressions ## | ||
|
||
Lambdas can refer to *outer variables* (see [Anonymous methods](programming-guide/statements-expressions-operators/anonymous-methods.md)) that are in scope in the method that defines the lambda function, or in scope in the type that contains the lambda expression. Variables that are captured in this manner are stored for use in the lambda expression even if the variables would otherwise go out of scope and be garbage collected. An outer variable must be definitely assigned before it can be consumed in a lambda expression. The following example demonstrates these rules. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this should stay "definitely assigned". That's the phrase the spec always uses for the analysis of assignment to a variable before it is used.
@BillWagner I've addressed all of your comments and will update the topic. |
✅ Validation status: passed
For more details, please refer to the build report. Note: If you changed an existing file name or deleted a file, broken links in other files to the deleted or renamed file are listed only in the full build report. |
@rpetrusha LGTM. |
Revisions to lambda expressions topic
Summary
Extensively revised with new examples and a section on tuples and lambda expressions.
Suggested Reviewers
@BillWagner @stevehoag @mairaw