Skip to Content

Lambdas and LINQ

Lambdas

Lambda expressions are just another way to write methods.

static bool SomePredicate(Point p) { return p.X * p.Y> 100000; } Predicate<Point> d = SomePredicate; Predicate<Point> d = delegate(Point p) { return p.X*p.Y> 100000; }; Predicate<Point> d = p => p.X* p.Y> 100000;

Closures

A lambda expression may use variables defined outside its context («outer variables»). here factor

void doSomething() { var factor = 2; Func<int, int> multiplier= n => n * factor; Console.WriteLine(multiplier(3)); //6 }

Be careful!! Writes the current value of i and not the value of i back when the delegate was created.

var actions = newList<Action>(); for(var i = 0; i < 10; i++) actions.Add(() => Console.WriteLine(i)); foreach(var action in actions) action(); // 101010101010101...

The solution to this is to declare a new “inner variable” for each iteration to be captured, instead of a single “outer variable” which is captured only once.

for(var i = 0; i < 10; i++) { varj = i; //each iteration gets its own,new variable j actions.Add(() => Console.WriteLine(j)); }

LINQ

LINQ = Language INtegrted Query are just like streams in Java. LINQ features can be used in a C# program by importing the System.Linq namespace.

LINQ is executed when results are accessed, not when the query is created. Execution happens when:

  • iterating over results
  • calling immediate execution methods like toList, Count etc.

NEVER modifystate using LINQ!!!

ForEach is NOT LINQ

persons.ForEach(p => Console.WriteLine(p.FirstName));

Method & Query Syntax

Method syntax resembles most other C# method calls, while query syntax resembles SQL. Query must begin with from clause, and end with select or group clause Between first from clause and last select/group clause, it can contain one or more of the following clauses:Where, Orderby, Join, Let, From, Into

// Method syntax var custQuery2 = customers.Where(c => c.City == "London"); var orderedByLength = names.OrderBy(n => n.Length); // Query syntax var custQuery = FROM c IN customers WHERE c.City == "London" SELECT c; // Mix var results = (FROM c IN Comedians SELECT c).Count();

Simple queries

// **** AGGREGATE **** var min = array.Min(); // All below can also be called straight on array var count = array.Count() var condCount = data.Count(x => x.Condition == true) var sumAges = persons.Sum(p => p.Age); var minAge = persons.Min(p => p.Age); var minAge = persons.Max(p => p.Age); var avgAge = persons.Average(p => p.Age); var simplePersons = persons.Select(p => new { Surname = p.Surname, Firstname = p.Firstname}) // creates an enumarable of anonymous class // **** CONVERSIONS **** data.ToArray(); // Convert to Array data.ToList(); // Convert to List data.ToDictionary( x=> x.Name ); // Convert to Dictionary keyed on Name // **** ELEMENT **** data.First() // Returns the first element data.First( x=> x.Type == Types.A ) // Returns the first element passing the condition data.FirstOrDefault() // Returns the first element or default data.FirstOrDefault( x => x.Type == Types.B ) // Returns the first element passing the condition or default data.Last() // Returns the last element data.Last( x=> x.Type == Types.A ) // Returns the last element passing the condition data.LastOrDefault( ) // Returns the last element or default* data.LastOrDefault( x => x.Type == Types.B ) // Returns the last element passing the condition or default* data.ElementAt(0) // Returns the element at position 0 // **** FILTERS **** var even array.Where(x => x%2==0) // Returns all elements passing the condition data.Where(( x, index) => index <= 4 && x.Type == Types.A) // The elements index can be passed into the delegate // **** GENERATION **** Enumerable.Range(1, 10); // Creates collection of 10 items between 1 and 10 Enumerable.Repeat(1, 10); // Creates a collection of 10 1s. // **** ORDERING **** data.OrderBy(x => x.Name); // Order by Name ASC data.OrderBy(x => x.Name).ThenBy(x => x.Age); // Order by Name ASC the Age ASC data.OrderBy(x => x.Name).ThenByDescending(x => x.Age); // Order by Name ASC then Age DESC data.OrderByDescending (x => x.Name); // Order by Name DESC data.OrderBy(x => x.Name).Reverse(); // Reverse elements // **** PARTITIONING **** data.Take (3); // Take 3 items data.Skip (3); // Skip 3 items data.TakeWhile (x=>x.Type ==Types.A); // Take all the items while the condition is met data.SkipWhile (x=>x.Type ==Types.A); // Skip all the items while the condition is met // **** PROJECTION **** data.Select(x => x.Name); // Select collection of a column data.Select(x => new { Name = x.Name, Age = x.Age }); // Select a collection of columns through an anonymus type // **** QUANTIFIERS **** if(array.Any(i=> i% 2 == 0)) if(array.All(i=> i% 2 == 0)) // **** SET **** data.Intersect(dataTwo); // Returns the union / intersection of data; elements in both collections data.Except(dataTwo); // Returns elements in data which are not in dataTwo data.Concat(dataTwo); // Concatonates both collections; appends dataTwo to data

Grouping

var users = new List<User>() { new User { Name = "John Doe", Age = 42, HomeCountry = "USA" }, new User { Name = "Jane Doe", Age = 38, HomeCountry = "USA" }, new User { Name = "Joe Doe", Age = 19, HomeCountry = "Germany" }, new User { Name = "Jenna Doe", Age = 19, HomeCountry = "Germany" }, new User { Name = "James Doe", Age = 8, HomeCountry = "USA" }, }; var usersGroupedByCountry = users.GroupBy(user => user.HomeCountry); foreach(var group in usersGroupedByCountry) { Console.WriteLine("Users from " + group.Key + ":"); foreach(var user in group) Console.WriteLine("* " + user.Name); }

Distinct

students.Distinct(); // Returns a collection of distinct elements students.Distinct (new StudentComparer()). // Distinct with providing an equality provider public class StudentComparer : IEqualityComparer<Student> { public bool Equals(Student x, Student y) { //First check if both object reference are equal then return true if(object.ReferenceEquals(x, y)) { return true; } //If either one of the object refernce is null, return false if (object.ReferenceEquals(x,null) || object.ReferenceEquals(y, null)) { return false; } //Comparing all the properties one by one return x.ID == y.ID && x.Name == y.Name; } public int GetHashCode(Student obj) { //If obj is null then return 0 if (obj == null) { return 0; } //Get the ID hash code value int IDHashCode = obj.ID.GetHashCode(); //Get the string HashCode Value //Check for null refernece exception int NameHashCode = obj.Name == null ? 0 : obj.Name.GetHashCode(); return IDHashCode ^ NameHashCode; } }

Join

IList<Student> studentList = new List<Student>() { new Student() { StudentID = 1, StudentName = "John", StandardID =1 }, new Student() { StudentID = 2, StudentName = "Moin", StandardID =1 }, new Student() { StudentID = 3, StudentName = "Bill", StandardID =2 }, new Student() { StudentID = 4, StudentName = "Ram" , StandardID =2 }, new Student() { StudentID = 5, StudentName = "Ron" } }; IList<Standard> standardList = new List<Standard>() { new Standard(){ StandardID = 1, StandardName="Standard 1"}, new Standard(){ StandardID = 2, StandardName="Standard 2"}, new Standard(){ StandardID = 3, StandardName="Standard 3"} }; var innerJoin = studentList.Join(// outer sequence standardList, // inner sequence student => student.StandardID, // outerKeySelector standard => standard.StandardID, // innerKeySelector (student, standard) => new // result selector { StudentName = student.StudentName, StandardName = standard.StandardName }); /* John - Standard 1 Moin - Standard 1 Bill - Standard 2 Ram - Standard 2 */

SelectMany

SelectMany() flattens the resulting sequences into one sequence, and invokes a result selector function on each element therein.

PetOwner[] petOwners = { new PetOwner { Name="Higa, Sidney", Pets = new List<string>{ "Scruffy", "Sam" } }, new PetOwner { Name="Ashkenazi, Ronen", Pets = new List<string>{ "Walker", "Sugar" } }, new PetOwner { Name="Price, Vernette", Pets = new List<string>{ "Scratches", "Diesel" } } }; // Query using SelectMany(). IEnumerable<string> query1 = petOwners.SelectMany(petOwner => petOwner.Pets); Console.WriteLine("Using SelectMany():"); // Only one foreach loop is required to iterate // through the results since it is a // one-dimensional collection. foreach (string pet in query1) { Console.WriteLine(pet); } // This code shows how to use Select() // instead of SelectMany(). IEnumerable<List<String>> query2 = petOwners.Select(petOwner => petOwner.Pets); Console.WriteLine("\nUsing Select():"); // Notice that two foreach loops are required to // iterate through the results // because the query returns a collection of arrays. foreach (List<String> petList in query2) { foreach (string pet in petList) { Console.WriteLine(pet); } Console.WriteLine(); } /* Using SelectMany(): Scruffy Sam Walker Sugar Scratches Diesel Using Select(): Scruffy Sam Walker Sugar Scratches Diesel */
Last updated on