You are on page 1of 23

C# 30

Introduction to LINQ 1

C# 3.0
Chapter 23 Introduction to LINQ

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 2

Why LINQ?
Data !!= Objects
State-of-the-art tooling has perfected OO
methodologies
The next challenge:
Accessing
ccess g and
a d integrating
teg at g non-OO
o OO
information, while abstracting away
its source

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 3

LINQ
LINQ is po
powered
ered b
by lang
language
age
enhancements
Some of which we have already seen (C# 3.0)
Some others we will examine in this chapter

LINQ is powered by a framework


LINQ to Objects the Enumerable extension
methods
LINQ to XML
LINQ to SQL
SQL, LINQ to Entities
Parallel LINQ (PLINQ) and other future technologies
d th
i C# 3
0 course
W
We recommend
the LINQ via
3.0
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 4

Implicit Typing
Local variables
ariables can have
ha e an implicit ttype
pe if
initialized within the declaration statement
var
var
var
var

i =5;
s=Hello;
e=newEmployee();
dict =newDictionary<string,List<string>>();

var a;

//Illegal!

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 5

Implicit Typing Notes


This is not VB6 Dim
This is not VB6 Variant
This is not System.Object
The
Th variable
i bl iis strongly
t
l ttyped
d
But y
you dont have to specify
p
y the type
yp

The variable must be initialized


null is not a valid initializer (what type?)
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 6

Anonymous Types
Remo
Removes
es the b
burden
rden of declaring data
dataholder types
yp
Narrows the Data Objects gap
var pi=new{
i
{
Name=John,
Pay CalcSalary()
Pay=CalcSalary()
};

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 7

Anonymous From Existing


Anon
Anonymous
mo s ttypes
pes can be generated using
sing
properties:
existing
g types
yp
p p
Personperson =...;
var partialDetails =new{
new{
person.Name,person.Age
};
//Equivalentto:
var partialDetails =new{
Name person Name Age person Age
Name=person.Name,Age=person.Age
};

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 8

Anonymous Types Notes


The generated type
t pe is immutable
imm table
Typical for data-holders, and thread-safe

The generated type is generic


Th
The same generic
i ttype can b
be reused:
d
var x=new{Name=A,Pay=15};
var y=new{Name=5,Pay=20};

Provides value semantics


Equals compares contents (like value types)
GetHashCode depends on contents (like value types)

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 9

Expression Trees
An e
expression
pression lambda can be capt
captured
red as
p
tree
an expression
Code = Data

The expression tree can be analyzed and


executed at runtime
E
Expression<Func<int,int>>square=x=>x*x;
i
F
i t i t
*
Func<int,int>compiled=square.Compile();
,
p
q
p
();
Console.WriteLine(compiled(5));

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 10

The Expression Tree


ntime the tree appears as follo
s
At rruntime,
follows:
Expression<Func<int,int,int>>

BinaryExpression
ExpressionType=Multiply
Type=Int32
ParameterExpression
Name=x,Type=Int32

ParameterExpression
Name=y,Type=Int32

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 11

Expression Trees Notes


Expression
E pression trees turn
t rn code into data
They can be used to dynamically analyze
expressions and provide different behavior
LINQ Providers use this extensively

E
Expression
i T
Tree Visualizer
Vi
li
(MSDN
sample)
http://tinyurl.com/ExpTreeVis

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 12

Review So Far
Implicit typing
t ping
Anonymous types
Expression
E
i ttrees

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 13

What Are Query Operators?


Q
Query
er operators are typically
t picall extension
e tension
p
on a sequence
q
of
methods that operate
elements
Some query operators return a sequence
of elements, some return a single value

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 14

Why Query Operators?


er operators facilitate declarati
e
Q
Query
declarative
programming
p
g
g instead of imperative
p
programming
List<int>sortedPrimes =newList<int>();
foreach (int i innumbers){
if(I P i (i))
if(IsPrime(i))sortedPrimes.Add(i);
t dP i
Add(i)
}
sortedPrimes.Sort();
sortedPrimes.ForEach(Console.WriteLine);
//Becomes:
Becomes
b
Wh
(i =>IsPrime(i)).OrderBy(i
I P i (i)) O d B (i =>i)
i)
numbers.Where(i
.ToList().ForEach(Console.WriteLine);

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 15

Developing Query Operators


Most q
query
er operators are very
er
g
straightforward
Lets develop some query operators that
operate on IEnumerable<T>

Where (filtering a sequence)


Order
d (ordering
( d i a sequence))
Select (projecting a sequence to another sequence)
Count(aggregating a sequence)
First(first element)
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 16

Implementing Where
staticclassEnumerableExtensions {
publicstaticIEnumerable<T>Where<T>(
thisIEnumerable<T>source,
Predicate<T>filter)
{
foreach (Telem insource)
if(filter(elem))
yieldreturnelem;
var
ar here is
}
}
IEnumerable<int>
var numbers=Range(0,100);
var evens=numbers.Where(i =>i%2==0);

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 17

Order
To order a seq
sequence,
ence we
e must
m st iterate it
relyy on a sorting
first (And
(
g container))
publicstaticIEnumerable<T>Order<T>(
thisIEnumerable<T>source){
SortedDictionary<T,bool>elements=
newSortedDictionary<T,bool>();
foreach (Telem insource)
elements.Add(elem,default(bool));
foreach (Tkeyinelements.Keys)
yieldreturnkey;
}

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 18

Select
ires a con
erter
Projection req
requires
converter:
//DefinedinSystem.Core.dll
//DefinedinSystem Core dll
publicdelegateTResult Func<T,TResult>(Targ);
publicstaticIEnumerable<S>Select<T,S>(
thisIEnumerable<T>source,
Func<T S>projection){
Func<T,S>projection){
foreach (Telem insource)
yieldreturnprojection(elem);
}

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 19

Count
Count, First
publicstaticlongCount<T>(
p
g
(
thisIEnumerable<T>source){
longcount=0;
var
ar enumerator=source.GetEnumerator();
en merator so r e GetEn merator()
while(enumerator.MoveNext())
++count;
;
returncount;
}
publicstaticTFirst<T>(
bli t ti TFi t<T>(
thisIEnumerable<T>source){
var enumerator=source.GetEnumerator();
();
if(enumerator.MoveNext())
returnenumerator.Current;
//Th
E t
//Throw:Emptysource
}

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 20

Our Operators In Action


This gi
gives
es us
s some room for
experimentation:
p
var numbers=Range(0,100);
var query=numbers.Where(i
query numbers Where(i =>i
>i %2==0);
%2 0);
Console.WriteLine("{0}numbers,first:{1}",
( { }
,
{ } ,
query.Count(),query.First());
foreach (int i inquery)
Console.WriteLine(i);
Employee[]employees=...;
var sortedEmpIds =employees.Select(e=>e.Id).Order();

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 21

Deferred Execution
ch as
Statements ssuch
var numbers=Range(0,100);
var evens=numbers.Where(i =>i%2==0);

provide deferred execution semantics


The enumeration is not executed yet!
foreach forces execution
Our Orderoperator forces execution
Our Count operator forces execution

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 22

Deferred Execution
This infers interesting conseq
consequences:
ences
We can produce infinite streams:
IEnumerable<int>Primes(int start){
for(;;++start)
if(IsPrime(start))
yieldreturnstart;
}

We can extract M out of N elements without touching


the
th restt
We can throw the query away without executing it

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 23

Review So Far
Q
Query
er operators as declarative
declarati e
p g
programming
g
Our hand-rolled query operators
Deferred
e e ed execution
e ecu o

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 24

Standard LINQ Query Operators


LINQ (in System.Core.dll)
S stem Core dll) pro
provides
ides
query
y operators
p
for
standard q
IEnumerable<T>
Filtering: Where,
Where Skip,
Skip Take,
Take Distinct,
Distinct OfType
Aggregation: Sum, Max, Min, Count, First, FirstOrDefault,
Single,
g , SingleOrDefault,
g
, Last,, LastOrDefault,, All,, Any,
y,
Aggregate, Contains
Ordering: OrderBy, OrderByDescending, ThenBy,
ThenByDescending
Grouping: GroupBy
Projection:
P j ti
S l t R
Select,
Repeat,
t SelectMany,
S l tM
T A
ToArray,
T Li t
ToList,
ToLookup, ToDictionary, Cast
Miscellaneous: Reverse
Reverse, Union
Union, Intersect
Intersect, Join
Join, Range
Range, Concat
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 25

Standard LINQ Query Operators


LINQ q
query
er operators are extension
e tension
methods in the static Enumerable class
Can be combined with our own!
As long as theres
there s no name collision

N
Note: S
So ffar we h
have di
discussed
d LINQ to
Objects query operators
Other LINQ provides do not work with IEnumerable

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 26

Examples Of LINQ Operators


var q=Enumerable.Range(0,100)
.Select(i =>new{Id=i,Name=i.ToString()})
.Where(e=>e.Name.StartsWith( 1 ))
.Where(e=>e.Name.StartsWith("1"))
.OrderByDescending(e=>e.Id)
.GroupBy(e=>e.Name.Substring(e.Name.Length1))
.Select(grp =>grp);
foreach (var groupinq){
Console.WriteLine("Key:"+group.Key);
Console.WriteLine("Elements:"+
group.Aggregate("",(a,e)=>a+=e.Name+""));
}

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 27

This Looks Familiar


io s
The SQL resemblance is ob
obvious:
S
SELECTproduct
C p oduct_name,COUNT(*)
a e, COU ( )
FROMorders
WHEREorders.date >...
GROUPBY
GROUPBYproduct_name
d t
orders
.Where(o=>o.Date >...)
.GroupBy(o=>o.ProductName)
.Select(grp
S l t(
=>new{

{
ProductName =grp.Key,
Count grp.Count()
Count=grp.Count()
});

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 28

Language Query Operators


Lang
Language
age query
q er operators are language
lang age
y
that are mapped
pp to q
query
y
keywords
operators
Not all query operators are accessible via keywords

C# integrated
g
q
query
y operators:
p

Projection: select
Filtering: where
Grouping: groupby
Od i
Ordering:
orderby
d b
Miscellaneous: join, let
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 29

Language Query Operators


var q2=
from i in Enumerable.Range(0,100)
select new{Id=i,Name=i.ToString()};
var q3=
from ein q2
where e.Name.StartsWith(
e Name StartsWith("1")
1 )
orderby e.Id descending
group eby e.Name.Substring(e.Name.Length1)
into g
select g;
foreach (var groupinq3)...

var here is
IEnumerable<Anon>
bl
var here is
IGrouping<string,Anon>

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 30

Syntactic Sugar
Lang
Language
age query
q er operators translate
y to LINQ q
query
y operators
p
directly
Query operators can be mixed:
int cnt =
(fromi inEnumerable.Range(0,100)
wherei %2==0
selecti).Count(i =>i >25);

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 31

Advanced Example: Joins


Most SQL
SQL-like
like joins are unnecessary
nnecessar
are often denormalized
because objects
j
var largeOrders =
fromcust incustomers
fromorderincust.Orders
whereorder.Amount >THRESHOLD
selectnew{cust.Name,order.Amount };
var largeOrders =
fromorderinorders
whereorder.Amount >THRESHOLD
join cust in customers
on order.CustomerId equals cust.Id
selectnew{cust.Name,order.Amount };
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 32

Advanced Example: Let


let is a helper keyword for complex
queries:
q
var query=
fromcincustomers
wherec.Joined.AddYears(1)<DateTime.Now
let orders=c.Orders.ToList()
selectnew{
Name=c.Name,
OrderQuantity =orders.Sum(o=>o.Amount)
OrderCount =orders.Count
};

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 33

LINQ to Objects
LINQ to Objects relies on the Enumerable
En merable
class, which contains q
query
y operators
p
as
extension methods
Any IEnumerable<T> can be queried
Additional types can be queried if they
implement the query pattern

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 34

Query Pattern
If the type is not IEnumerable,
IEn merable there are
y to make it q
queryable:
y
two ways
Add instance methods for query operators:
Select<T>, Where, OrderBy, etc.
Add extension methods in a separate
p
class for q
query
y
operators: Select<T>, Where, OrderBy, etc.

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 35

Query Pattern: Select


classPayrollSystem {
publicIEnumerable<T>Select<T>(
Func<Employee,T>selector){
returnemployees.Select(selector);
}
internalList<Employee>employees=...;
//Moreimplementationomitted
}
PayrollSystem payroll=...;
var names=fromemployeeinpayroll
select employee.Name;

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 36

Query Pattern: Select Extension


Alternati
Alternatively,
el an e
extension
tension method can be
used:
classPayrollSystem {
internalList<Employee>employees=...;
//Moreimplementationomitted
}
staticclassPayrollExtensions {
publicstaticIEnumerable<T>Select<T>(
thisPayrollSystem payroll,
Func<Employee,T>selector){
returnpayroll.employees.Select(selector);
}
}
PayrollSystem payroll=...;
var names=fromemployeeinpayroll
selectemployee.Name;
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 37

Query Pattern: Where


classPayrollSystem {
publicIEnumerable<Employee>Where(
Func<Employee,bool>filter){
returnemployees.Where(filter);
}
internalList<Employee>employees=...;
//Select<T>omitted
}
PayrollSystem payroll=...;
var names=fromemployeeinpayroll
where employee.Salary >220
selectemployee.Name;

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 38

Query Pattern Notes


The q
query
er pattern implementation can also
query
y behavior
be used to customize q
For example, specify additional filters for the Where
query
que y operator
ope ato (even
(e e if the
t e object is
s IEnumerable)
u e ab e)
staticclassPayrollExtensions {
publicstaticIEnumerable<Employee>Where(
thisPayrollSystem payroll,
Func<Employee,bool>filter){
returnpayroll.employees.Where(
e=>e.City==London&& filter(e));
}
}

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 39

LINQ to Objects Applicability


An
Any object model is a potential data
q
source for LINQ queries
The requirements are not strict either IEnumerable
or the query pattern

Make
M k your object
bj t models
d l LINQ
LINQ-friendly!
f i dl !

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 40

LINQ to Strings
strings=Guid.NewGuid().ToString();
stringdigitsOnly =
newstring((fromcins
whereChar.IsDigit(c)
selectc)
)
.ToArray());
Console.WriteLine(s+\n+digitsOnly);
//Output:
8faf837df0a64e698ac523635452f6f9
883706469852363545269

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 41

LINQ to Reflection
//Findallcollection initializable types
//Findallcollectioninitializable
//(Roughsketch)
var queryableTypes =
fromasm inAppDomain.CurrentDomain.GetAssemblies()
fromtinasm.GetExportedTypes()
wheret GetInterfaces() Any(itf =>
wheret.GetInterfaces().Any(itf
itf.IsGenericType &&
((itf.IsGenericTypeDefinition
&&itf ==typeof(ICollection<>))||
||
(!itf.IsGenericTypeDefinition &&
itf GetGenericTypeDefinition()==
itf.GetGenericTypeDefinition()==
typeof(ICollection<>)))
)||
typeof(IEnumerable).IsAssignableFrom(t)&&
t.GetMethods().Any(m=>m.Name =="Add")
selectt;
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 42

LINQ to File System


//FindalllargeDLLsinSystem32
var largeDllFiles =
fromfileinDirectory GetFiles(
fromfileinDirectory.GetFiles(
Environment.GetFolderPath(
Environment.SpecialFolder.System))
p
y
))
letinfo=newFileInfo(file)
whereinfo.Extension ==".dll"&&
info.Length
info Length >5000000
selectinfo.FullName;

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 43

LINQ to Objects Performance


1 Dont turn every for
1.
f and foreach loop
q y
into a LINQ query
2. yieldreturn is often slower than
h d ll d enumerators
hand-rolled
t
or forloops
f l
3 Invoking lambdas is often more
3.
expensive than an inline loop body
4. Measure to ensure sane results and sane
number of calls (run-time complexity)

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 44

Chapter 23 Exercises

C# 3.0, QUERY OPERATORS


AND LINQ TO OBJECTS
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

C# 30

Introduction to LINQ 45

Chapter Summary
More C# 3.0
3 0 language features
Anonymous types, implicit typing, expression trees

C# 3.0
3 0 meets LINQ
Query operators, query pattern

LINQ to Objects

Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel

You might also like