Extension Methods, Lambda Expressions, LINQ Operators, Expressions, Projections, Aggregations Extension Methods, Lambda Expressions, LINQ Operators, Expressions,

Slides:



Advertisements
Similar presentations
The Microsoft Technical Roadshow 2007 Language Enhancements and LINQ Daniel Moth Developer & Platform Group Microsoft Ltd
Advertisements

LINQ and Collections An introduction to LINQ and Collections.
Extension Methods, Anonymous Types LINQ Query Keywords, Lambda Expressions Svetlin Nakov Telerik Corporation
C# and LINQ Yuan Yu Microsoft Research Silicon Valley.
C# 3.0 Tom Roeder CS fa. Version 3 From PDC 2005 preview compiler available LINQ: language-integrated query High level points: adds native query.

2.3 Cool features in C# academy.zariba.com 1. Lecture Content 1.Extension Methods 2.Anonymous Types 3.Delegates 4.Action and Func 5.Events 6.Lambda Expressions.
C# 3.0 and LINQ Pavel Yosifovich CTO, Hi-Tech College
A tour of new features introducing LINQ. Agenda of LINQ Presentation We have features for every step of the way LINQ Fundamentals Anonymous Functions/Lambda.
XML files (with LINQ). Introduction to LINQ ( Language Integrated Query ) C#’s new LINQ capabilities allow you to write query expressions that retrieve.
Differences between C# and C++ Dr. Catherine Stringfellow Dr. Stewart Carpenter.
LINQ Programming in C# LINQ CSE Prof. Roger Crawfis.
 Introduction  What is LINQ  Syntax  How to Query  Example Program.
REFACTORING Lecture 4. Definition Refactoring is a process of changing the internal structure of the program, not affecting its external behavior and.
LINQ, An IntroLINQ, An Intro Florin−Tudor Cristea, Microsoft Student Partner.
Eric Vogel Software Developer A.J. Boggs & Company.
Presidents of United States of America. George Washington
Operators, Expressions, Projections, Aggregations Svetlin Nakov Telerik Corporation
American Government McGraw- Hill © The McGraw-Hill Companies, Inc., 1998 Year Percent Sources: Harold W. Stanley and Richard G. Niemi, Vital Statistics.
CHARLES UNIVERSITY IN PRAGUE faculty of mathematics and physics Advanced.NET Programming I 11 th Lecture Pavel Ježek
Lambdas and Streams. Functional interfaces Functional interfaces are also known as single abstract method (SAM) interfaces. Package java.util.function.
Getting familiar with LINQ to Objects Florin−Tudor Cristea, Microsoft Student Partner.
Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.
Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009.
Functional Programming Extension Methods, Lambda Expressions, LINQ Svetlin Nakov Technical Trainer Software University
Extension Methods, Anonymous Types LINQ Query Keywords, Lambda Expressions Based on material from Telerik Corporation.
Introduction to LINQ Lecture # 19 August Introduction How do you interrogate/manipulate data? What if you could do the work in a type-safe," string-free.
Neal Stublen How does XMLReader work?  XmlReader.Read() Advances to next node XmlReader properties access node name, value, attributes,
Generics Collections. Why do we need Generics? Another method of software re-use. When we implement an algorithm, we want to re-use it for different types.
Generics and Collections. Introduction Generics New feature of J2SE 5.0 Provide compile-time type safety Catch invalid types at compile time Generic methods.
 Language Integrated Query  Make query a part of the language  Component of.NET Framework 3.5  Shipped with Visual Studio 2008.
1 Compiler Construction (CS-636) Muhammad Bilal Bashir UIIT, Rawalpindi.
Session 08 Module 14: Generics and Iterator Module 15: Anonymous & partial class & Nullable type.
Hoang Anh Viet Hà Nội University of Technology Chapter 1. Introduction to C# Programming.
 Although VERY commonly used, arrays have limited capabilities  A List is similar to an array but provides additional functionality, such as dynamic.
Introduction to LINQ Chapter 11. Introduction Large amounts of data are often stored in a database—an organized collection of data. A database management.
Database Systems Design, Implementation, and Management Coronel | Morris 11e ©2015 Cengage Learning. All Rights Reserved. May not be scanned, copied or.
Object Oriented Programming Generic Collections and LINQ Dr. Mike Spann
CSCI 3327 Visual Basic Chapter 8: Introduction to LINQ and Collections UTPA – Fall 2011.
Inside LINQ to Objects How LINQ to Objects work Inside LINQ1.
PROGRAMMING IN C#. Collection Classes (C# Programming Guide) The.NET Framework provides specialized classes for data storage and retrieval. These classes.
 In the java programming language, a keyword is one of 50 reserved words which have a predefined meaning in the language; because of this,
Satisfy Your Technical Curiosity C# 3.0 Raj Pai Group Program Manager Microsoft Corporation
Dictionaries, Hash Tables, Collisions Resolution, Sets Svetlin Nakov Telerik Corporation
Information Processing: Encoding Serial Position Effect in Recalling.
IAP C# 2011 Lecture 2: Delegates, Lambdas, LINQ Geza Kovacs.
LINQ to DATABASE-2.  Creating the BooksDataContext  The code combines data from the three tables in the Books database and displays the relationships.
2: Basics Basics Programming C# © 2003 DevelopMentor, Inc. 12/1/2003.
LINQ Language Integrated Query LINQ1. LINQ: Why and what? Problem Many data sources: Relational databases, XML, in-memory data structures, objects, etc.
Functional Programming Extension Methods, Lambda Expressions, LINQ SoftUni Team Technical Trainers Software University
LINQ and Lambda Expressions Telerik Software Academy LINQ Overview.
Visual Basic 2010 How to Program © by Pearson Education, Inc. All Rights Reserved.
C# Fundamentals An Introduction. Before we begin How to get started writing C# – Quick tour of the dev. Environment – The current C# version is 5.0 –
Chapter  Array-like data structures  ArrayList  Queue  Stack  Hashtable  SortedList  Offer programming convenience for specific access.
Chapter 11.  Large amounts of data are often stored in a database—an organized collection of data.  A database management system (DBMS) provides mechanisms.
Functional Programming Data Aggregation and Nested Queries Ivan Yonkov Technical Trainer Software University
Lecture 8: Collections, Comparisons and Conversions. Svetla Boytcheva AUBG, Spring COS 240 Object-Oriented Languages.
Part 1: Overview of LINQ Intro to LINQ Presenter: PhuongNQK.
Jim Fawcett CSE681 – Software Modeling and Analysis Fall 2016
Introduction to LINQ and Generic Collections
Jim Fawcett CSE681 – Software Modeling and Analysis Fall 2013
Intro to LINQ Part 2 – Concepts and LINQ to Objects
Language Integrated Query: (LINQ) An introduction
Visual Basic 2010 How to Program
Microsoft .NET 3. Language Innovations Pan Wuming 2017.
.NET and .NET Core 5.2 Type Operations Pan Wuming 2016.
Introduction to LINQ Chapter 11 10/28/2015 Lect 4 CT1411.
Introduction to LINQ Chapter 11.
LINQ - 2 Ravi Kumar C++/C# Team.
CS4540 Special Topics in Web Development LINQ to Objects
Presentation transcript:

Extension Methods, Lambda Expressions, LINQ Operators, Expressions, Projections, Aggregations Extension Methods, Lambda Expressions, LINQ Operators, Expressions, Projections, Aggregations Svetlin Nakov Telerik Corporation

1. Extension Methods 2. Anonymous Types 3. Lambda Expressions 4. LINQ Building Blocks 5. Query Operators and Expressions 6. Query Expression Trees 7. LINQ to Objects: Querying Collections 8. Projection, Conversion, Aggregation 9. Sorting, Grouping, Joins, Nested Queries 2

 Once a type is defined and compiled into an assembly its definition is, more or less, final  The only way to update, remove or add new members is to recode and recompile the code  Extension methods allow existing compiled types to gain new functionality  Without recompilation  Without touching the original assembly 4

 Extension methods  Defined in a static class  Defined as static  Use this keyword before its first to specify the class to be extended  Extension methods are "attached" to the extended class  Can also be called from statically through the defining static class 5

6 public static class Extensions { public static int WordCount(this string str) public static int WordCount(this string str) { return str.Split(new char[] { ' ', '.', '?' }, return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length; StringSplitOptions.RemoveEmptyEntries).Length; }}... static void Main() { string s = "Hello Extension Methods"; string s = "Hello Extension Methods"; int i = s.WordCount(); int i = s.WordCount(); Console.WriteLine(i); Console.WriteLine(i);}

7 public static void IncreaseWidth( this IList list, int amount) this IList list, int amount){ for (int i = 0; i < list.Count; i++) for (int i = 0; i < list.Count; i++) { list[i] += amount; list[i] += amount; }}... static void Main() { List ints = List ints = new List { 1, 2, 3, 4, 5 }; new List { 1, 2, 3, 4, 5 }; ints.IncreaseWidth(5); // 6, 7, 8, 9, 10 ints.IncreaseWidth(5); // 6, 7, 8, 9, 10}

Live Demo

 Anonymous types  Encapsulate a set of read-only properties and their value into a single object  No need to explicitly define a type first  To define an anonymous type  Use of the new var keyword in conjunction with the object initialization syntax 10 var point = new { X = 3, Y = 5 };

 At compile time, the C# compiler will autogenerate an uniquely named class  The class name is not visible from C#  Using implicit typing ( var keyword) is mandatory 11 // Use an anonymous type representing a car var myCar = new { Color = "Red", Brand = "BMW", Speed = 180 }; new { Color = "Red", Brand = "BMW", Speed = 180 }; Console.WriteLine("My car is a {0} {1}.", myCar.Color, myCar.Brand); myCar.Color, myCar.Brand);

 Anonymous types are reference types directly derived from System.Object  Have overridden version of Equals(), GetHashCode(), and ToString()  Do not have == and != operators overloaded 12 var p = new { X = 3, Y = 5 }; var q = new { X = 3, Y = 5 }; Console.WriteLine(p == q); // false Console.WriteLine(p.Equals(q)); // true

 You can define and use arrays of anonymous types through the following syntax: 13 var arr = new[] { new { X = 3, Y = 5 }, new { X = 3, Y = 5 }, new { X = 1, Y = 2 }, new { X = 1, Y = 2 }, new { X = 0, Y = 7 } new { X = 0, Y = 7 }}; foreach (var item in arr) { Console.WriteLine("({0}, {1})", Console.WriteLine("({0}, {1})", item.X, item.Y); item.X, item.Y);}

Live Demo

 A lambda expression is an anonymous function containing expressions and statements  Used to create delegates or expression tree types  All lambda expressions use the lambda operator =>, which is read as "goes to"  The left side of the lambda operator specifies the input parameters  The right side holds the expression or statement 16

 Usually used with collection extension methods like FindAll() and Count() 17 List list = new List () { 1, 2, 3, 4 }; List evenNumbers = list.FindAll(x => (x % 2) == 0); list.FindAll(x => (x % 2) == 0); foreach (var num in evenNumbers) { Console.Write("{0} ", num); Console.Write("{0} ", num);}Console.WriteLine(); // 2 4 list.RemoveAll(x => x > 3); // 1 2 3

18 var pets = new Pet[] { new Pet { Name="Sharo", Age=8 }, new Pet { Name="Sharo", Age=8 }, new Pet { Name="Rex", Age=4 }, new Pet { Name="Rex", Age=4 }, new Pet { Name="Strela", Age=1 }, new Pet { Name="Strela", Age=1 }, new Pet { Name="Bora", Age=3 } new Pet { Name="Bora", Age=3 }}; var sortedPets = pets.OrderBy(pet => pet.Age); foreach (Pet pet in sortedPets) { Console.WriteLine("{0} -> {1}", Console.WriteLine("{0} -> {1}", pet.Name, pet.Age); pet.Name, pet.Age);}

 Lambda code expressions: 19 List list = new List () { 20, 1, 4, 8, 9, 44 }; { 20, 1, 4, 8, 9, 44 }; // Process each argument with code statements List evenNumbers = list.FindAll((i) => { Console.WriteLine("value of i is: {0}", i); Console.WriteLine("value of i is: {0}", i); return (i % 2) == 0; return (i % 2) == 0; }); }); Console.WriteLine("Your even numbers are:"); foreach (int even in evenNumbers) Console.Write("{0}\t", even); Console.Write("{0}\t", even);

 Lambda functions can be stored in variables of type delegate  Delegates are typed references to functions  Standard function delegates in.NET:  Func, Func, Func, … 20 Func boolFunc = () => true; Func intFunc = (x) => x intFunc = (x) => x < 10; if (boolFunc() && intFunc(5)) Console.WriteLine("5 < 10"); Console.WriteLine("5 < 10");

Live Demo

 Language Integrated Query (LINQ) query keywords  from – specifies data source and range variable  where – filters source elements  select – specifies the type and shape that the elements in the returned sequence  group – groups query results according to a specified key value  orderby – sorts query results in ascending or descending order 23

 select, from and where clauses: 24 int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; var querySmallNums = from num in numbers from num in numbers where num < 5 where num < 5 select num; select num; foreach (var num in querySmallNums) { Console.Write(num.ToString() + " "); Console.Write(num.ToString() + " ");} // The result is

 Nested queries: 25 string[] towns = { "Sofia", "Varna", "Pleven", "Ruse", "Bourgas" }; { "Sofia", "Varna", "Pleven", "Ruse", "Bourgas" }; var townPairs = from t1 in towns from t1 in towns from t2 in towns from t2 in towns select new { T1 = t1, T2 = t2 }; select new { T1 = t1, T2 = t2 }; foreach (var townPair in townPairs) { Console.WriteLine("({0}, {1})", Console.WriteLine("({0}, {1})", townPair.T1, townPair.T2); townPair.T1, townPair.T2);}

 Sorting with оrderby : 26 string[] fruits = { "cherry", "apple", "blueberry", "banana" }; { "cherry", "apple", "blueberry", "banana" }; // Sort in ascending sort var fruitsAscending = from fruit in fruits from fruit in fruits orderby fruit orderby fruit select fruit; select fruit; foreach (string fruit in fruitsAscending) { Console.WriteLine(fruit); Console.WriteLine(fruit);}

Live Demo

 Software developers spend a lot of time to obtain and manipulate data  Data can be stored in  Collections  Databases  XML documents  etc...  As of.NET 3.5 developers can use LINQ – a simplified approach to data manipulation 29

 LINQ is a set of extensions to.NET Framework  Encompasses language-integrated query, set, and transform operations  Consistent manner to obtain and manipulate "data" in the broad sense of the term  Query expressions can be defined directly within the C# programming language  Used to interact with numerous data types  Converted to expression trees at compile time and evaluated at runtime 30

 LINQ allows query expressions to manipulate:  Any object implementing IEnumerable  Any object implementing IEnumerable  Collections of objects  Relational databases  XML documents  The query expressions are based on numerous SQL-like query operators  Intentionally designed to look and feel very similar to SQL expressions 31

 "LINQ" is the term used to describe this overall approach to data access  LINQ to Objects  LINQ over objects implementing IEnumerable  LINQ over objects implementing IEnumerable  LINQ to SQL and LINQ to Entities implement LINQ over relational data  LINQ to DataSet is a superset of LINQ to SQL  LINQ to XML is LINQ over XML documents 32

33 LINQ enabled data sources LINQ to Objects Objects LINQ to XML XML LINQ enabled ADO.NET LINQ to DataSets LINQ to SQL LINQ to Entities Relational Data Others Others … C# VB.NET.NET Language-Integrated Query (LINQ)

 All LINQ query operations consist of three distinct actions: 1.Obtain the data source 2.Create the query 3.Execute the query 34

 The interface IEnumerable is universal LINQ data source  Implemented by arrays and all.NET generic collections  Enables enumerating over a collection of elements  A sequence in LINQ means a collection implementing the IEnumerable interface  Any variable declared as IEnumerable for type T is considered a sequence of type T 36

 Most of the Standard Query Operators are extension methods in the static class System.Linq.Enumerable  Prototyped with an IEnumerable as their first argument  E.g. Min(IEnumerable ), Where(IEnumerable, Func )  Use the Cast or OfType operators to perform LINQ queries on legacy, non-generic.NET collections 37

 When you have a collection of data, a common task is to extract a subset of items based on a given requirement  You want to obtain only the items with names that contain a number  Or don’t have embedded spaces  LINQ query expressions can greatly simplify the process  Query expressions are written in a declarative query syntax introduced in C#

 LINQ query expressions are written in a declarative SQL-like syntax  Example: extracting a subset of array containing items with names of more than 6 characters: 40 string[] games = {"Morrowind", "BioShock", "Daxter", "The Darkness", "Half Life", "System Shock 2"}; "The Darkness", "Half Life", "System Shock 2"}; IEnumerable subset = from g in games from g in games where g.Length > 6 where g.Length > 6 orderby g orderby g select g; select g; foreach (string s in subset) Console.WriteLine("Item: {0}", s); Console.WriteLine("Item: {0}", s);

Live Demo

 In LINQ a query is a basic language construction  Just like classes, methods and delegates in C#  Query expressions are used to query and transform data from any LINQ-enabled data source  A LINQ query is not executed until  You iterate over the query results  You try to access any of the elements in the result set 42

 Query operators in C# are keywords like:  from, in, where, orderby, select, …  For each standard query operator a corresponding extension method exists  E.g. where  Where(IEnumerable )  At compile time the C# compiler translates query expressions into expression trees  Expression trees are sequences of method calls (from System.Linq.Enumerable ) 43

 The basic syntax of LINQ queries is:  This selects all elements in games data source  You can apply criteria by the operator where  Any valid C# boolean expression can be used 44 IEnumerable subset = from g in games select g; from g in games select g; IEnumerable subset = from g in games from g in games where g.Price < 20 where g.Price < 20 select g; select g; var subset = games.Select(g => g); games.Select(g => g); var subset = games.Select(g => g). games.Select(g => g). Where(g => g.Price g.Price < 20);

 Two sets of LINQ standard operators  Operating on IEnumerable  Operating on IEnumerable  Operating on IQueryable  Operating on IQueryable  LINQ query operators are shorthand versions for various extension methods  Defined in System.Linq.Enumerable type  Example: 45 IEnumerable subset = games.Where(g => g.Price g.Price < 20); var subset = from g in games from g in games where g.Price < 20 where g.Price < 20 select g; select g;

 The standard query operators provide query capabilities including  Filtering – where  Projection – select, selectMany  Aggregation – Sum, Max, Count, Average  Sorting – orderby  Grouping – groupby  … and many more 46

47 string[] games = {"Morrowind", "BioShock","Half Life", "The Darkness","Daxter", "System Shock 2"}; "The Darkness","Daxter", "System Shock 2"}; // Build a query expression using extension methods // granted to the Array via the Enumerable type var subset = games.Where(game => game.Length > 6). OrderBy(game => game).Select(game => game); OrderBy(game => game).Select(game => game); foreach (var game in subset) Console.WriteLine(game); Console.WriteLine(game);Console.WriteLine(); var subset = from g in games from g in games where g.Length > 6 where g.Length > 6 orderby g orderby g select g; select g;

Live Demo

 A query expression tree is an efficient data structure representing a LINQ expression  Type of abstract syntax tree used for storing parsed expressions from the source code  Lambda expressions often translate into query expression trees  IQueryable is interface implemented by query providers (e.g. LINQ to SQL, LINQ to XML, LINQ to Entities)  IQueryable objects use expression trees 50

 LINQ queries can be performed over two standard.NET interfaces:  IEnumerable  IEnumerable  At compile time IL is emitted  IQueryable  IQueryable  At compile time a query expression tree is emitted  Both are evaluated at runtime 51

 When any element of the IQueryable result is being accessed for the first time  A query is generated from the expression tree and is executed 52 int[] nums = new int[] { 6, 2, 7, 1, 9, 3 }; 6, 2, 7, 1, 9, 3 }; var numsLessThanFour = from i in nums from i in nums where i < 4 where i < 4 select i; select i; foreach (var item in numsLessThanFour) Console.WriteLine(item); Console.WriteLine(item); Query is generated and executed here Variable is of type IQueryable Variable is of type IQueryable

 IQueryable uses expression trees which provide it mechanisms:  For smart decisions and optimizations when query is generated  Based on analysis of expression trees  Optimizing multiple nested or complex queries  Combining multiple queries into very efficient single one 53

 LINQ to Objects refers to using LINQ queries directly over IEnumerable collection  Without the an intermediate LINQ provider or API, such as LINQ to SQL or LINQ to XML  Applicable to any enumerable collection  The old school data retrieval approach  Write complex foreach loops that specify how to retrieve data from a collection  Тhe LINQ approach – write declarative code that describes what to be retrieved 55

 LINQ queries offer three main advantages over traditional foreach loops  They are more concise and easy-to-read  Especially when filtering by multiple conditions  Provide powerful filtering, ordering, and grouping capabilities  Can be ported to other data sources with little or no modification 56

 LINQ to Objects is performing SQL-like queries on in-memory data collections and arrays 57 string[] presidents = { "Adams", "Arthur", "Buchanan", "Bush", "Carter","Cleveland","Clinton", "Coolidge", "Bush", "Carter","Cleveland","Clinton", "Coolidge", "Eisenhower", "Fillmore", "Ford", "Garfield","Grant", "Eisenhower", "Fillmore", "Ford", "Garfield","Grant", "Harding", "Harrison", "Hayes", "Hoover", "Jackson", "Harding", "Harrison", "Hayes", "Hoover", "Jackson", "Jefferson", "Johnson", "Kennedy", "Lincoln", "Jefferson", "Johnson", "Kennedy", "Lincoln", "Madison", "McKinley", "Monroe", "Nixon", "Pierce", "Madison", "McKinley", "Monroe", "Nixon", "Pierce", "Polk", "Reagan", "Roosevelt", "Taft", "Taylor", "Polk", "Reagan", "Roosevelt", "Taft", "Taylor", "Truman", "Tyler", "Van Buren", "Washington", "Truman", "Tyler", "Van Buren", "Washington", "Wilson"}; "Wilson"}; string president = presidents.Where(p => p.StartsWith("Lin")).First(); presidents.Where(p => p.StartsWith("Lin")).First();Console.WriteLine(president); string president = (from p in presidents (from p in presidents where p.StartsWith("Lin") where p.StartsWith("Lin") select p).First(); select p).First();

Live Demo

59 string text = "Historically, the world of data …"; … string searchTerm = "data"; string[] source = text.Split( new char[] { '.', '?', '!', ' ', ';', ':', ',' }, new char[] { '.', '?', '!', ' ', ';', ':', ',' }, StringSplitOptions.RemoveEmptyEntries); StringSplitOptions.RemoveEmptyEntries); // Use ToLower() to match both "data" and "Data" var matchQuery = from word in text from word in text where word.ToLower() == searchTerm.ToLower() where word.ToLower() == searchTerm.ToLower() select word; select word; int wordCount = matchQuery.Count(); matchQuery.Count(); int wordCount = text.Select( w => w.toLower() == w => w.toLower() == searchTerm.ToLower()).Count(); searchTerm.ToLower()).Count();

Live Demo

 What can we query?  Not everything can be queried by LINQ to Objects  The objects need to be a collection  It must implement the IEnumerable interface  The good news  Almost all standard collections in.NET Framework implements IEnumerable  Almost all standard collections in.NET Framework implements IEnumerable 62

 What can be queried using LINQ to Objects?  Arrays – T[]  Generic lists – List  Generic lists – List  Generic dictionaries – Dictionary  Generic dictionaries – Dictionary  Strings – string  Other collections that implements IEnumerable  Other collections that implements IEnumerable 63

 Any kind of arrays can be used with LINQ  Can be even an untyped array of objects  Queries can be applied to arrays of custom objects  Example: 64 Book[] books = { new Book { Title="LINQ in Action" }, new Book { Title="LINQ in Action" }, new Book { Title="LINQ for Fun" }, new Book { Title="LINQ for Fun" }, new Book { Title="Extreme LINQ" } }; new Book { Title="Extreme LINQ" } }; var titles = books.Where(book => book.Title.Contains("Action")).Where(book => book.Title.Contains("Action")).Select(book => book.Title);.Select(book => book.Title); var titles = from b in books from b in books where b.Title.Contains("Action") where b.Title.Contains("Action") select b.Title; select b.Title;

 The previous example can be adapted to work with a generic list  List, LinkedList, Queue, Stack, HashSet, etc. 65 List books = new List () { new Book { Title="LINQ in Action" }, new Book { Title="LINQ in Action" }, new Book { Title="LINQ for Fun" }, new Book { Title="LINQ for Fun" }, new Book { Title="Extreme LINQ" } }; new Book { Title="Extreme LINQ" } }; var titles = books.Where(book => book.Title.Contains("Action")).Where(book => book.Title.Contains("Action")).Select(book => book.Title);.Select(book => book.Title);

Live Demo

 Although System.String may not be perceived as a collection at first sight  It actually is a collection, because it implements IEnumerable  It actually is a collection, because it implements IEnumerable  String objects can be queried with LINQ to Objects, like any other collection 67 var count = "Non-letter characters in this string: 8".Where(c => !Char.IsLetter(c)).Where(c => !Char.IsLetter(c)).Count();.Count();Console.WriteLine(count); // The result is: 8 var count = (from c in "Non-letter…" (from c in "Non-letter…" where !Char.IsLetter(c) where !Char.IsLetter(c) select c).Count(); select c).Count();

 An aggregation operation computes a single value from a collection of values  Example of aggregation of field over a sequence of employees 69NameSalary Bay Ivan 12500,00 Bat Rambo 13500,00 Baba Yaga 43300,00 Kiro the King 29800,00 Bay Mangal 25000, MAX(Salary)125500,00

 Average()  Calculates the average value of a collection  Count()  Counts the elements in a collection  Max()  Determines the maximum value in a collection  Sum()  Sums the values in a collection 70

 Count( )  Max() 71 double[] temperatures = {28.0, 19.5, 32.3, 33.6, 26.5, 29.7}; {28.0, 19.5, 32.3, 33.6, 26.5, 29.7}; int highTempCount = temperatures.Count(p => p > 30); Console.WriteLine(highTempCount); // The result is: 2 double[] temperatures = {28.0, 19.5, 32.3, 33.6, 26.5, 29.7}; {28.0, 19.5, 32.3, 33.6, 26.5, 29.7}; double maxTemp = temperatures.Max(); Console.WriteLine(maxTemp); // The result is: 33.6 var highTemp = (from p in temperatures (from p in temperatures where p > 30 where p > 30 select p).Count(); select p).Count(); var highTemp = (from p in temperatures (from p in temperatures select p).Max(); select p).Max();

 Projection refers to the act of transforming the elements of a collection into a different type  The resulting type is defined by the developer  Projection operators in LINQ  Select – projects single values that are based on a transform function  SelectMany – projects collections of values into a new collection containing all values 72

 Select(<transform-function)) 73 List words = new List () { "an", "apple", "a", "day" }; new List () { "an", "apple", "a", "day" }; var query = from word in words from word in words select word.Substring(0, 1); select word.Substring(0, 1); foreach (string s in query) { Console.Write("{0} ", s); Console.Write("{0} ", s);} // The result is: a a a d var query = words.Select(w => words.Select(w => w.Substring(0,1)); w.Substring(0,1));

 SelectMany( ) 74 string[] sentence = new string[] { "The quick brown", "The quick brown", "fox jumped over", "fox jumped over", "the lazy dog"}; "the lazy dog"}; // SelectMany returns nine strings // (sub-iterates the Select result) IEnumerable allWords = sentence.SelectMany(segment => segment.Split(' ')); sentence.SelectMany(segment => segment.Split(' ')); foreach (var word in allWords) Console.Write(" {0}", word); Console.Write(" {0}", word); // Result: The quick brown fox jumped over the lazy dog No LINQ equvalent

Live Demo

 Converting a collection to a different type  Can change the type of the collection  Can change the type of the elements  Conversion operations in LINQ queries are useful in a variety of applications  For example:  Enumerable.AsEnumerable  Enumerable.AsEnumerable  Enumerable.OfType  Enumerable.OfType  Enumerable.ToArray(TSource) 76

 If start with " As "  Change the static type of the source collection but do not enumerate it  If start with " To "  Enumerate the source collection and turn each item into the corresponding collection type 77 string[] towns = {"Sofia", "Plovdiv", "Varna", "Bourgas", "Pleven"}; {"Sofia", "Plovdiv", "Varna", "Bourgas", "Pleven"}; IEnumerable strings = towns.AsEnumerable (); towns.AsEnumerable (); List list = towns.ToList();

 A sorting operation orders the elements of a sequence based on one or more attributes  Standard query operator  OrderBy(…)  OrderByDescending(…)  ThenBy(…) – performs a secondary sort in ascending order  ThenByDescending(…)  Reverse(…) 78

79 string[] words = { "Bay Kolio", "Pinokio", "Dedo Mraz", "Baba Yaga", "Bay Mangal" }; "Dedo Mraz", "Baba Yaga", "Bay Mangal" }; IEnumerable query = from word in words from word in words orderby word.Length, word.Substring(0, 1) descending orderby word.Length, word.Substring(0, 1) descending select word; select word; foreach (string str in query) Console.WriteLine(str); Console.WriteLine(str); /* The result is: Pinokio Pinokio Dedo Mraz Dedo Mraz Bay Kolio Bay Kolio Baba Yaga Baba Yaga Bay Mangal Bay Mangal*/ var query = words.Select(word => word). words.Select(word => word). OrderBy(word => word.Length). OrderBy(word => word.Length). ThenByDescending( ThenByDescending( word => word.Substring(0, 1)); word => word.Substring(0, 1));

 Operation of putting data into groups  The elements in each group share a common value for some attribute  Example 80

 GroupBy()  Groups elements that share a common attribute, called key  Each group is represented by a sequence of IGrouping(TKey,TElement) objects  ToLookup()  Inserts elements into a Lookup(TKey, TElement) based on a key selector function  Distinct()  Returns distinct elements form a collection 81

82 var people = new[] { new { Name = "Kiki", Town = "Plovdiv"}, new { Name = "Kiki", Town = "Plovdiv"}, new { Name = "Pepi", Town = "Sofia"}, new { Name = "Pepi", Town = "Sofia"}, new { Name = "Koko", Town = "Sofia"}, new { Name = "Koko", Town = "Sofia"}, new { Name = "Mimi", Town = "Plovdiv"} new { Name = "Mimi", Town = "Plovdiv"}}; var peopleByTowns = from p in people from p in people group p by p.Town; group p by p.Town; foreach (var town in peopleByTowns) { Console.Write("Town {0}: ", town.Key); Console.Write("Town {0}: ", town.Key); foreach (var person in town) foreach (var person in town) Console.Write("{0} ", person.Name); Console.Write("{0} ", person.Name); Console.WriteLine(); Console.WriteLine();} var peopleByTowns = people.GroupBy(t => t.Town); people.GroupBy(t => t.Town);

83 int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; var numberGroups = from n in numbers from n in numbers group n by n % 3; group n by n % 3; foreach (var g in numberGroups) { Console.Write("Remainder: {0} -> ", g.Key); Console.Write("Remainder: {0} -> ", g.Key); foreach (var n in g) foreach (var n in g) Console.Write("{0} ", n); Console.Write("{0} ", n); Console.WriteLine(); Console.WriteLine();} // Remainder: 2 -> // Remainder: 1 -> // Remainder: 0 -> var numberGroups = numbers.GroupBy(n => n % 3); numbers.GroupBy(n => n % 3);

 Action of relating or associating one data source object with a second data source object  The two data source objects are associated through a common value or attribute 84

 Join  Joins two sequences based on key selector function  And extracts the joined pairs of values  GroupJoin  Joins two sequences based on key selector functions  And groups the resulting matches for each element 85

86 var owners = new[] { new { Name = "Koko", Town = "Plovdiv"}, new { Name = "Koko", Town = "Plovdiv"}, new { Name = "Pepi", Town = "Sofia"}, new { Name = "Pepi", Town = "Sofia"},}; var pets = new[] { new { Name = "Sharo", Owner = owners[0] }, new { Name = "Sharo", Owner = owners[0] }, new { Name = "Rex", Owner = owners[1] }, new { Name = "Rex", Owner = owners[1] }, new { Name = "Poohy", Owner = owners[0] }, new { Name = "Poohy", Owner = owners[0] },}; var petsWithOwners = from o in owners from o in owners join p in pets on o.Name equals p.Owner.Name join p in pets on o.Name equals p.Owner.Name select new { Owner = o.Name, Pet = p.Name }; select new { Owner = o.Name, Pet = p.Name }; foreach (var p in petsWithOwners) Console.WriteLine("{0} owned by {1}", p.Pet, p.Owner); Console.WriteLine("{0} owned by {1}", p.Pet, p.Owner); var petsWithOwners = owners.Join(pets, (o => o.Name), (p => p.Owner.Name), (o => o.Name), (p => p.Owner.Name), (o, p) => new {o.Name, p.Name }); (o, p) => new {o.Name, p.Name });

Live Demo

 The queries can be nested  For example:  Suppose we have collections of Person and collections of Role objects  We want get all roles for given person (ID = 1) 88 var query = people.Where(p => p.ID == 1).Where(p => p.ID == 1).SelectMany(p => roles.SelectMany(p => roles.Where(r => r.ID == p.RoleID).Where(r => r.ID == p.RoleID).Select(r =>.Select(r => new { p.FirstName, p.LastName, r.Role })); new { p.FirstName, p.LastName, r.Role }));

Live Demo

Questions?