Articles » Languages » C# » General

C# Lectures - Lecture 9:Lambda expressions

Sergey Kizyan, 5 Jun 2016 CPOL

4.88 (10 votes)

1

2

3

4

5

4.88/5 - 10 votes

μ 4.88, σa 0.98 [?]

9th from my series. This is relatively short but it is introduction to big LINQ part

Download 09_Lambda.zip - 9.3 KB

Full Lectures Set

C#Lectures - Lecture 1: Primitive Types

C# Lectures - Lecture 2: Work with text in C#: char, string, StringBuilder, SecureString

C# Lectures - Lecture 3 Designing Types in C#. Basics You Need to Know About Classes

C# Lectures - Lecture 4: OOP basics: Abstraction, Encapsulation, Inheritance, Polymorphism by C# example

C# Lectures - Lecture 5:Events, Delegates, Delegates Chain by C# example

C# Lectures - Lecture 6: Attributes, Custom attributes in C#

C# Lectures - Lecture 7: Reflection by C# example

C# Lectures - Lecture 8: Disaster recovery. Exceptions and error handling by C# example

Introduction

In this article I'm going to talk about anonymous functions that are named lambda expressions. Lambda expressions is the relatively new technology that allows you create delegates or expression tree types. Using lambda expressions you can create functions that you pass as arguments to another functions or return them as value of function calls. Also lambda expressions are more than useful with LINQ. Most developers and writers describe lambda expressions together with delegates and events, but as this is relatively new technology, I've decided to have separate article about it. Since version 3, C# has supported lambda expressions. Lambda expressions have been used in computer languages as far back as LISP; they were conceptualized in 1936 by Alonzo Church, an American mathematician. These expressions provide shorthand syntax for specifying an algorithm.

Anonymous types

Before diving into lambda expressions I want to highlight quickly another short topic - anonymous types. Anonymous types provide a convenient way to encapsulate read-only properties to single object without definition of type for this object. While compilation compiler generates a name for the anonymous type, but it is not visible for developer. Type for the read-only properties in anonymous type is also defined by compiler. By itself anonymous types doesn't seems to be something cool, but in combination with LINQ and Lambda expressions they give a real power. We'll review it later on in this chapter.

Following code demonstrates usage of anonymous type:

//---------------ANONYMOUS TYPES------------------------
Console.WriteLine("-----------ANONYMOUS TYPES----------------");
var anonym1 = new { int_val = 1, double_val = 0.11, string_val = "some string" };
Console.WriteLine("anonym1 type is: " + anonym1.GetType());
Console.WriteLine("double_val type is: " + anonym1.double_val.GetType());
Console.WriteLine("int_val type is: " + anonym1.int_val.GetType());
Console.WriteLine("string_val type is: " + anonym1.string_val.GetType());
Result of it will be:

Anonymous types limitations:

They can have only public read-only properties

They don't have methods or other type members

You can cast anonymous type only to object

If two anonymous types have equal definition they are treated by compiler as same type and share same metadata

There are several ways of initialization for anonymous types. Few of them are provided below:

int i = 10;
string s = "string value";
var anonym2 = new { int_val = i, string_val = s };
var anonym3 = new { i, s };
var anonym4 = new { anonym2, anonym3 };

Building lambda expression, lambda operator

When you create lambda expression you should use lambda operator =>. Lambda operator separates input variable from the left side with the lambda body on the right. Lambda operator can be read as "goes to". In lambda expression you put input parameters, if you have them, on the left side of operator and  expression or statement from the right side of the lambda operator. So lambda expression looks like:

<arguments if any>   =>   <expression>

or

<arguments if any>   =>   <statement block>

Initially before lambda expressions there were designed anonymous methods that you can build path them to functions that expect delegates. Sometimes this is very convenient and useful\readable in code. Lambda then was created to provide more specific syntax for anonymous methods as delegates and for sure they are more than useful for LINQ query expressions as they provide with ability to write compact methods that you path as arguments for subsequent evaluation.

Below is an example how we replace delegate with lambda function:

//Declarign the delegate:

public delegate int MyDelegate(string s, int i);

//Implement the caller and delegate:

public static void DelegateCaller(MyDelegate input)
{
int res = input("Delegate Caller", 5);
Console.WriteLine("Delegate result is: " + res);
}
public static int DelegateFunction(string s, int i)
{
Console.WriteLine("Delegate function string: " + s + " int:" + i);
return 1;
}

//calling via delegate and via lambda

Console.WriteLine("-----------LAMBDA EXPRESSIONS----------------");
//calling by delegate
DelegateCaller(new MyDelegate(DelegateFunction));
//creating lambda delegate
MyDelegate del = (str, dig) =>
{
Console.WriteLine("Delegate lambda string: " + str + " int: " + dig);
return 2;
};
DelegateCaller(new MyDelegate(del));

To play with the example you can download sources attached to this article

Lambda expression syntaxes

You can specify parameters in parenthesis is you need to path more than one parameter:

(car, engineSize) => car.engine >= engine Size

You can specify types for parameters to avoid confusion

<code> (ClassCar car, int engineSize) => car.engine >= engine Size</code>

You can have lambda expression without parameters:

<code> () => Console.WriteLine("Parameter less lambda");</code>

If you have multiple statements in body they should be in curly braces:

x =>

{

Console.WriteLine("Few statements lambda");

return x*x;

}

You can use local variable in expression body that will be visible only inside your lambda expression

x =></code>

Variable scope in lambdas

In lambdas you can refer to variables that are in the scope of method where they are defined and in type where they are defined. If your will use such variable in scope of lambda it will be stored in memory for lambda even if in other cases it would be garbage collected. Please see example below that demonstrates how local variable in method where lambda is defined is still in memory with proper value even so in usual cases it will not work:

//declaring delegate:

public delegate int SomeDelegate(int input);

//implementing sample function

public void ScopeExample()
{
//local variable that will be hold for delegate
//even after ScopeExample is running out of the
//scope and released from memory
int j = 5;
m_del = (x) =>
{
Console.WriteLine("Input parameter is : " + x);
Console.WriteLine("Local variable is: " + j);
return j + x;
};
int i = m_del(5);
Console.WriteLine("Delegate internal result is: " + i);
}

//testing

//delegates variable scope
Program test = new Program();
test.ScopeExample();
int k = test.m_del(10);
Console.WriteLine("Delegate external result is: " + k);

You can download sources attached to play with it

I'm copying below from MSDN rules for variable scope in lambdas:

A variable that is captured will not be garbage-collected until the delegate that references it goes out of scope.

Variables introduced within a lambda expression are not visible in the outer method.

A lambda expression cannot directly capture a ref or out parameter from an enclosing method.

A return statement in a lambda expression does not cause the enclosing method to return.

A lambda expression cannot contain a goto statement, break statement, or continue statement whose target is outside the body or in the body of a contained anonymous function.

Sources

http://www.introprogramming.info/english-intro-csharp-book/read-online/chapter-22-lambda-expressions-and-linq/

http://weblogs.asp.net/scottgu/new-orcas-language-feature-lambda-expressions

http://www.tutorialsteacher.com/linq/linq-lambda-expression

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Sergey Kizyan

Architect

Ukraine

Working on different projects and technologies from web to low level core programming, from scripting languages to C++. With all this stuff my personal opinion is that C#,.NET and Microsoft environment is the best thing programmer may have. Basing on it I prefer to publish only about my favorite technologies that are .NET and Azure now.

P.S. Looking for partnership and cooperation in outsourcing.

You may also be interested in...

10 Ways to Boost COBOL Application Development

Generate and add keyword variations using AdWords API

Visual COBOL New Release: Small point. Big deal

Window Tabs (WndTabs) Add-In for DevStudio

SAPrefs - Netscape-like Preferences Dialog

WPF: If Carlsberg did MVVM Frameworks: Part 3 of n

Comments and Discussions

7 messages have been posted for this article Visit http://www.codeproject.com/Articles/1104790/Csharp-Lectures-Lecture-Lambda-expressions to post and view comments on this article, or click here to get a print view with messages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160730.2 | Last Updated 6 Jun 2016

Article Copyright 2016 by Sergey Kizyan
Everything else Copyright © CodeProject, 1999-2016