Module 2. LINQ and C#
Features of using with LINQ:
- extension methods
- lambda expressions
Evolving the Language
LINQ on whiteboard (in design phase):
Sequence<Employee> scotts = employees.Where(Name == "Scott");
Emulate LINQ in C#2.0:
IEnumerable<Employee> scotts =
EnumerableExtensions.Where(employees, delegate(Employee e)
{
return e.Name == "Scott";
});
LINQ today
var scotts =
from e in employees
where e.Name == "Scott"
select e;
There is a compiler in background working hard enough to achieve this feature
The Power of IEnumerable
Reference:
Both List
& array inherit & implement an interface IEnumerable<T>
. It can represent various data type that can be be iterated.
You can hide any sort of data structure behind IEnumerable<T>
interface
Instead of using generic collection like List as shown below, after using IEnumerable<Employee>
we can iterate it using GetEnumerator
Employee[] developers = new Employee[]
{
new Employee {Id = 1, Name = "Scott"},
new Employee {Id = 2, Name = "Chris"}
};
transform to
IEnumerable<Employee> developers = new Employee[]
{
new Employee {Id = 1, Name = "Scott"},
new Employee {Id = 2, Name = "Chris"}
};
Overall, IEnumerable<T>
Interface's utility
Exposes the enumerator, which supports a simple iteration over a collection of a specified type.
Creating an Extension Method
Reference:
- Must Read: LINQ Extension Methods (dotnettutorial)
- Must Read: Extension Methods in C# (dotnettutorial)
- Extension Methods (C# Programming Guide)
e.g. of extention methods
public static class StringExtensions
{
static public double ToDouble(this string data)
{
double result = double.Parse(data);
return result;
}
}
To create extension methods:
- 1st parameter of an exention methods uses
this
modifier. This parameter is called binding parameter - Type of binding parameter is class that want to extend
After creating extensions, we can invoke this static method with instance syntax
string text = "43.35";
double data = text.ToDouble();
Note:
- Static extension method cannot overwrite existing method of that instance. (e.g. replace
ToString()
) - Extension can only exist in the namespace it defined.
- We can use the extension method as a normal static method
Understanding Lambda Expressions
Reference:
- Must Read: Lambda Expressions in C# (dotnettutorials)
- Must Read: Anonymous method C#
- Lambda expressions (C# reference)
The Lambda Expression in C# is the shorthand for writing the anonymous function. So we can say that the Lambda Expression in C# is nothing but to simplify the anonymous function in C#. As the name suggests, an anonymous method is a method without having a name. Anonymous methods in C# can be defined using the keyword delegate and can be assigned to a variable of the delegate type. In simple terms, an anonymous method is a method without a name.
How to create Lambda Expression in C#
To create a lambda expression in C#, we need to specify the input parameters (if any) on the left side of the lambda operator
=>
, and we need to put the expression or statement block on the other side.
e.g. LINQ filtering using named method
IEnumerable<string> filteredList = cities.Where(StartsWithL);
public bool StartsWithL(string name)
{
return name.StartsWith("L");
}
Problem: too many code for a filter method
e.g. LINQ filtering using Anonymous Method
IEnumerable<string> filteredList = cities.Where(delegate(string s )
{ return s.StartsWith("L");});
Problem: too many syntax, and hard to read
Solution to problems above: Lambda Expression, clean and concise
IEnumberable<string> filteredList =
cities.Where(s => s.StartsWith("L"));
Using Func and Action Types
Reference:
Why we need generic delegates?
For different methods, we need create different delegates. It leads cumberson codes.
Generic delegates can save us from creating all these functions
Many LINQ operator use this type to work with delegate
3 different generic delegate
3 different generic delegate:
- Func
- Action
- Predicate
Syntax for defining Func type:
Fun<param1_datatype, param2_datatype, ..., return_type> delegate_func_name = new Fun<param1_datatype, param2_datatype, ..., return_type>(method_or_lambda);
After defining generic delegate, we can invoke them like normal delegate
generic delegate + lambda expression is very powerful
Essence of LINQ
LINQ take IEnumerable<T>
, and return IEnumerable<T>
. Hence, we can chain these together
Using var
for implicit Typing
Reference:
var
is not dynamic typing, it's deducted before compiling
var can be used to declare any built-in data type or a user-defined type or an anonymous type variable.
- Implicitly-typed variables must be initialized at the time of declaration;
- It also cannot be initilaized as
NULL
- It also cannot be initilaized as
- Multiple declarations of var variables in a single statement are not allowed.
- var cannot be used for function parameters.
var
's benefit & usage:
var
inforeach
var
to replace longIEnumerable<...>
Query Syntax vs. Method Syntax
Reference:
Query Syntax:
- starts with
from
- filter/find/etc. using
where
, ororderby
- ends with
select
orgroup
C# LINQ translate Query Syntax into Method Syntax. Query Syntax is more fancier, but more functions are available in Method Syntax.
How to choose:
- Determined by the query.
- Target: easier to maintain
Summary
Feature in C# that make LINQ work:
- Extension: where LINQ live. (
using System.Linq
). These extension know how to sort/filter, but don't know criteria - Lambda: Create criteria for filter/sort using simple syntax
- Query Syntax