0% found this document useful (0 votes)
230 views34 pages

LINQ To Objects: C# Development

This document discusses LINQ (Language Integrated Query) in C# and provides examples of using LINQ to query arrays. It introduces LINQ and its purpose of providing a unified syntax for querying different data sources. It then demonstrates querying an array without LINQ using manual iteration and conditional logic, and querying the same array with LINQ using query expressions and operators like Where and Select. The document also notes that LINQ queries use deferred execution, executing only when enumerated rather than when created.

Uploaded by

Andy Olsen
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
230 views34 pages

LINQ To Objects: C# Development

This document discusses LINQ (Language Integrated Query) in C# and provides examples of using LINQ to query arrays. It introduces LINQ and its purpose of providing a unified syntax for querying different data sources. It then demonstrates querying an array without LINQ using manual iteration and conditional logic, and querying the same array with LINQ using query expressions and operators like Where and Select. The document also notes that LINQ queries use deferred execution, executing only when enumerated rather than when created.

Uploaded by

Andy Olsen
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 34

LINQ to Objects

Chapter 11

C# Development
Contents
1. Introduction to LINQ
2. Using LINQ with arrays
3. Using LINQ with collections
4. LINQ under the hood
5. Additional LINQ techniques

2
1. Introduction to LINQ
 What is LINQ?
 The purpose of LINQ
 LINQ variations
 A few technical details

3
What is LINQ?
 LINQ = "Language Integrated Query"

 Or to put it another way:


• A set of C# (VB etc) keywords and .NET types,
methods, etc.
• … to query data from various data sources

4
The Purpose of LINQ
 LINQ provides a unified syntax for querying data
• Regardless of where the data is coming from

 Better than the pre-LINQ situation, where you


have to use completely different query syntaxes
• Objects in memory
 Use arrays and/or .NET collection classes APIs
• Relational data
 Use ADO.NET connections, ADO.NET DataSets, etc.
• XML
 Use DOM, XmlReader, XmlWriter, etc.

5
LINQ Variations
 There are several LINQ variations currently
available:
• LINQ to objects
• LINQ to XML
• LINQ to DataSet
• LINQ to Entities

 We'll examine all of these techniques in this and


coming chapters

6
A Few Technical Details
 LINQ queries use SQL-like syntax
• Via C# keywords such as select, from, where, etc.
• Can manipulate any data source that implements the
IEnumerable<T> generic interface
• LINQ queries are strongly typed

 C# / .NET features utilized by LINQ:


• Implicitly-typed local variables
• Extension methods
• Object/collection initialization syntax
• Anonymous types
• Lambda expressions
7
2. Using LINQ with Arrays
 Overview
 Querying arrays without LINQ
 Querying arrays with LINQ
 C# LINQ query operators
 Deferred execution
 Immediate execution

8
Overview
 In this section, we'll show how to use LINQ to
query data in an array
• See the LinqOverArrays project
• Automatically references LINQ-related assemblies

Defines types that represent the core LINQ API

Defines types for LINQ to DataSets

Defines types for LINQ to XML

9
Querying Arrays Without LINQ
 Here's a traditional array-processing example
• Uses manual iteration / conditional logic
• Doesn't use LINQ
private static void DemoNonLinq()
private static void DemoNonLinq()
{
{
//
// Here's
Here's an
an array
array of
of strings.
strings.
string[] cities = { "Boston", "New York", "Dallas", "St. Paul", "Las Vegas" };
string[] cities = { "Boston", "New York", "Dallas", "St. Paul", "Las Vegas" };
// Get the cities that contain a space character.
// Get the cities that contain a space character.
string[] citiesWithSpaces = new string[cities.Length];
string[] citiesWithSpaces = new string[cities.Length];
for (int i = 0; i < cities.Length; i++)
for (int i = 0; i < cities.Length; i++)
{
{
if
if (cities[i].Contains("
(cities[i].Contains(" "))
"))
citiesWithSpaces[i]
citiesWithSpaces[i] == cities[i];
cities[i];
}}

Console.WriteLine("Cities with spaces (without using LINQ): ");


Console.WriteLine("Cities with spaces (without using LINQ): ");
foreach (string s in citiesWithSpaces)
foreach (string s in citiesWithSpaces)
{
{
if
if (s
(s !=
!= null)
null)
Console.WriteLine("City:
Console.WriteLine("City: {0}",
{0}", s);
s);
}}
}}

10
Querying Arrays With LINQ
 Here's the equivalent example using LINQ
private static void DemoLinq()
private static void DemoLinq()
{
{
// Here's an array of strings.
// Here's an array of strings.
string[] cities = { "Boston", "New York", "Dallas", "St. Paul", "Las Vegas" };
string[] cities = { "Boston", "New York", "Dallas", "St. Paul", "Las Vegas" };
//
// Use
Use aa LINQ
LINQ query
query expression
expression to
to get
get the
the cities
cities that
that contain
contain aa space
space character.
character.
var subset = from g in cities
var subset = from g in cities
where g.Contains(" ")
where g.Contains(" ")
orderby g.Length
orderby g.Length
ascending
ascending
select g;
select g;
Console.WriteLine("\nCities
Console.WriteLine("\nCities with
with spaces
spaces (using
(using LINQ):
LINQ): ");
");
foreach (var s in subset)
foreach (var s in subset)
Console.WriteLine("City:
Console.WriteLine("City: {0}",
{0}", s);
s);
}}

• Builds a LINQ query expression using query operators


• Assigns to var (it's IEnumerable<string> actually)
• Query is executed when we enumerate it in the loop
11
C# LINQ Query Operators
 Here are some of the most commonly used C#
LINQ query operators:
• from, in
• where
• select
• join, on, equals, into
• orderby, ascending, descending
• group, by

12
Deferred Execution
 LINQ queries use a "deferred execution" model
• Executed when you enumerate the query, not when
you create it
• Therefore, if you enumerate a query several times, the
query will be executed afresh each time
private static void DemoDeferredExecution()
private static void DemoDeferredExecution()
{
{
int[] examMarks = { 62, 75, 85, 59, 96, 80 };
int[] examMarks = { 62, 75, 85, 59, 96, 80 };
// Get the "A" grades, i.e. >= 70.
// Get the "A" grades, i.e. >= 70.
var
var subset
subset == from
from mm in
in examMarks
examMarks where
where mm >=
>= 70
70 select
select m;
m;
Console.WriteLine("\nA-grade
Console.WriteLine("\nA-grade exams
exams (LINQ
(LINQ query
query is
is executed
executed here):");
here):");
foreach (var m in subset)
foreach (var m in subset)
Console.WriteLine("Mark: {0}", m);
Console.WriteLine("Mark: {0}", m);
// Change some data in the array.
// Change some data in the array.
examMarks[0]
examMarks[0] == 99;
99;
Console.WriteLine("\nA-grade
Console.WriteLine("\nA-grade exams
exams (LINQ
(LINQ query
query is
is executed
executed AGAIN
AGAIN here):");
here):");
foreach (var m in subset)
foreach (var m in subset)
Console.WriteLine("Mark:
Console.WriteLine("Mark: {0}",
{0}", m);
m);
}
}
13
Immediate Execution
 If you want to execute a query immediately:
• Invoke the ToArray<T>() extension method
 Executes the query and places the result in a T[] array
• Or invoke the ToList<T>() extension method
 Executes the query and places the result in a List<T>
private static void DemoImmediateExecution()
private static void DemoImmediateExecution()
{
{
int[]
int[] examMarks
examMarks == {{ 62,
62, 75,
75, 85,
85, 59,
59, 96,
96, 80
80 };
};
//
// Execute
Execute query
query immediately,
immediately, and
and get
get result
result as
as int[].
int[].
int[] arrayOfGradeAs
int[] arrayOfGradeAs = =
(from m in examMarks where m >= 70 select m).ToArray<int>();
(from m in examMarks where m >= 70 select m).ToArray<int>();
// Get data RIGHT NOW as List<int>.
// Get data RIGHT NOW as List<int>.
List<int> listOfGradeAs =
List<int> listOfGradeAs =
(from m in examMarks where m >= 70 select m).ToList<int>();
(from m in examMarks where m >= 70 select m).ToList<int>();
}
}

14
3. Using LINQ with Collections
 Overview
 Querying generic collections
 Querying raw collections
 Filtering data

15
Overview
 In this section, we'll show how to use LINQ to
query data in a collection
• See the LinqOverCollections project

 We'll be querying collections of Product objects


• Here's the Product class
class
class Product
Product
{{
public string Description { get; set; }
public string Description { get; set; }
public double Price { get; set; }
public double Price { get; set; }
public
public int
int InStock
InStock {{ get;
get; set;
set; }}
}}

16
Querying Generic Collections
 You can use generic collections in LINQ queries
• Generic collections implement IEnumerable<T> 
private static void DemoLinqGenericCollection()
private static void DemoLinqGenericCollection()
{
{
// List<> of Product objects.
// List<> of Product objects.
List<Product>
List<Product> products
products == new
new List<Product>()
List<Product>()
{
{
new Product { Description = "3D HD-TV", Price = 1500, InStock = 3 },
new Product { Description = "3D HD-TV", Price = 1500, InStock = 3 },
new Product { Description = "BlueRay Player", Price = 200, InStock = 10 },
new Product { Description = "BlueRay Player", Price = 200, InStock = 10 },


};
};
Console.WriteLine("Expensive
Console.WriteLine("Expensive products:");
products:");
var subset1 = from p in products where p.Price > 300 select p;
var subset1 = from p in products where p.Price > 300 select p;
foreach (var p in subset1)
foreach (var p in subset1)
{
{
Console.WriteLine("\t{0}", p.Description);
Console.WriteLine("\t{0}", p.Description);
}
}
Console.WriteLine("Scarce
Console.WriteLine("Scarce expensive
expensive products:");
products:");
var
var subset2
subset2 == from
from pp in
in products
products where
where p.Price
p.Price >> 300
300 &&
&& p.InStock
p.InStock << 55 select
select p;
p;
foreach (var p in subset2)
foreach (var p in subset2)
{{
Console.WriteLine("\t{0}", p.Description);
Console.WriteLine("\t{0}", p.Description);
}
}
}
}
17
Querying Raw Collections
 You can't use raw collections in LINQ queries
• Raw collections don't implement IEnumerable<T> 
• You must convert into an IEnumerable<T> collection
private static void DemoLinqGenericCollection()
private static void DemoLinqGenericCollection()
{
{
// Raw ArrayList of Product objects.
// Raw ArrayList of Product objects.
ArrayList
ArrayList products
products == new
new ArrayList()
ArrayList()
{{
new
new Product
Product {{ Description
Description == "3D
"3D HD-TV",
HD-TV", Price
Price == 1500,
1500, InStock
InStock == 33 },},
new
new Product
Product {{ Description
Description == "BlueRay
"BlueRay Player",
Player", Price
Price == 200,
200, InStock
InStock == 10
10 },
},


};
};
// Transform ArrayList into an IEnumerable<T> collection.
// Transform ArrayList into an IEnumerable<T> collection.
var enumerable = products.OfType<Product>();
var enumerable = products.OfType<Product>();
Console.WriteLine("Expensive
Console.WriteLine("Expensive products
products (from
(from raw
raw collection
collection originally):");
originally):");
var subset = from p in enumerable where p.Price > 300 select p;
var subset = from p in enumerable where p.Price > 300 select p;
foreach (var p in subset)
foreach (var p in subset)
{
{
Console.WriteLine("\t{0}", p.Description);
Console.WriteLine("\t{0}", p.Description);
}
}
}
}

18
Filtering Data
 You can filter data in a collection, to retrieve only
those objects of a specific type
• Use the OfType<T>() extension method
private
private static
static void
void DemoFilter()
DemoFilter()
{
{
// Raw ArrayList of various object types.
// Raw ArrayList of various object types.
ArrayList myStuff = new ArrayList()
ArrayList myStuff = new ArrayList()
{{
3,
3, 12,
12, 1964,
1964, true,
true, new
new Product(),
Product(), "super
"super swans"
swans"
};
};
// Transform ArrayList into an IEnumerable<int>, ignores the non-ints.
// Transform ArrayList into an IEnumerable<int>, ignores the non-ints.
IEnumerable<int> myInts = myStuff.OfType<int>();
IEnumerable<int> myInts = myStuff.OfType<int>();
Console.WriteLine("Ints from the raw collection:");
Console.WriteLine("Ints from the raw collection:");
foreach (int i in myInts)
foreach (int i in myInts)
{
{
Console.WriteLine("\t{0}",
Console.WriteLine("\t{0}", i);
i);
}
}
}
}

19
4. LINQ Under the Hood
 Overview
 Using C# query operators
 LINQ extension methods
 Using anonymous methods
 Using lambda expressions

20
Overview
 In this section, we'll explain what actually happens
when you use C# LINQ query operators
• See the LinqUnderTheHood project

 We'll show how to implement the same LINQ


query using:
• C# LINQ query operators
• Extension methods and anonymous methods
• Extension methods and lambda expressions

21
Using C# Query Operators
 Here's a simple example using C# query operators
• Nothing new here 
private static void DemoOperators()
private static void DemoOperators()
{
{
string[]
string[] cities
cities == {{ "Boston",
"Boston", "New
"New York",
York", "Dallas",
"Dallas", "St.
"St. Paul",
Paul", "Las
"Las Vegas"
Vegas" };
};
// Create a LINQ query expression using C# query operators.
// Create a LINQ query expression using C# query operators.
var subset = from c in cities
var subset = from c in cities
where c.Contains(" ")
where c.Contains(" ")
orderby c.Length
orderby c.Length
select c;
select c;
Console.WriteLine("Cities with spaces (using C# query operators): ");
Console.WriteLine("Cities with spaces (using C# query operators): ");
foreach (var s in subset)
foreach (var s in subset)
Console.WriteLine("City: {0}", s);
Console.WriteLine("City: {0}", s);
}
}

22
LINQ Extension Methods
 The C# query operators are short-hand syntax
• Under the cover, they represent extension methods
that are added to IEnumerable<T>
• Defined in the System.Linq.Enumerable class
• Located in the System.Core.dll assembly

 For example:
where
where g.Contains("
g.Contains(" ")
")

IEnumerable<T> Where<TSrc>(this IEnumerable<TSrc> source, Func<TSrc, bool> predicate)


IEnumerable<T> Where<TSrc>(this IEnumerable<TSrc> source, Func<TSrc, bool> predicate)

delegate TResult Func<in TSrc, out TResult>(TSrc item)


delegate TResult Func<in TSrc, out TResult>(TSrc item)

References a method that takes an item and returns bool,


indicating whether to keep the item in the query's result set
23
Using Anonymous Methods
 Here's the equivalent example…
• This time using anonymous methods explicitly
• Each anonymous method is represented by an
appropriate Func<> delegate
private static void DemoAnonymousMethods()
private static void DemoAnonymousMethods()
{
{
string[] cities = { "Boston", "New York", "Dallas", "St. Paul", "Las Vegas" };
string[] cities = { "Boston", "New York", "Dallas", "St. Paul", "Las Vegas" };
//
// Build
Build Func<>
Func<> delegates
delegates for
for Where(),
Where(), OrderBy(),
OrderBy(), and
and Select()
Select() extension
extension methods.
methods.
Func<string, bool> whereFunc = delegate(string c) { return c.Contains(" "); };
Func<string, bool> whereFunc = delegate(string c) { return c.Contains(" "); };
Func<string, int> orderbyFunc = delegate(string c) { return c.Length; };
Func<string, int> orderbyFunc = delegate(string c) { return c.Length; };
Func<string, string> selectFunc = delegate(string c) { return c; };
Func<string, string> selectFunc = delegate(string c) { return c; };
// Pass the Func<> delegates into extension methods.
// Pass the Func<> delegates into extension methods.
var subset = cities.Where(whereFunc)
var subset = cities.Where(whereFunc)
.OrderBy(orderbyFunc)
.OrderBy(orderbyFunc)
.Select(selectFunc);
.Select(selectFunc);
Console.WriteLine("\nCities with spaces (using anonymous methods): ");
Console.WriteLine("\nCities with spaces (using anonymous methods): ");
foreach (var c in subset)
foreach (var c in subset)
Console.WriteLine("City: {0}", c);
Console.WriteLine("City: {0}", c);
}
}

24
Using Lambda Expressions
 It's a small step from using anonymous methods
to using lambda expressions
private static void DemoLambdaExpressions()
private static void DemoLambdaExpressions()
{
{
string[]
string[] cities
cities == {{ "Boston",
"Boston", "New
"New York",
York", "Dallas",
"Dallas", "St.
"St. Paul",
Paul", "Las
"Las Vegas"
Vegas" };
};
// Pass lambda expressions into extension methods
// Pass lambda expressions into extension methods
var subset = cities.Where(c => c.Contains(" "))
var subset = cities.Where(c => c.Contains(" "))
.OrderBy(c => c.Length)
.OrderBy(c => c.Length)
.Select(c => c);
.Select(c => c);
Console.WriteLine("\nCities
Console.WriteLine("\nCities with
with spaces
spaces (using
(using lambda
lambda expressions):
expressions): ");
");
foreach (var s in subset)
foreach (var s in subset)
Console.WriteLine("City:
Console.WriteLine("City: {0}",
{0}", s);
s);
}}

 Lambda expression syntax reminder:


Where(
• Represents a method that takes a single parameter
Where( cc =>
=> c.Contains("
c.Contains(" ")
") )) • Method body returns the boolean result of c.Contains()

25
5. Additional LINQ Techniques
 Overview
 Selecting full objects
 Selecting specific fields
 Selecting projections
 Set-based operations
 Aggregate operations

26
Overview
 In this section, we'll show how to use some
additional LINQ techniques
• See the AdditonalLinqTechniques project

 We'll be querying collections of Product objects


• Here's the Product class, same as earlier in chapter
class
class Product
Product
{{
public string Description { get; set; }
public string Description { get; set; }
public double Price { get; set; }
public double Price { get; set; }
public
public int
int InStock
InStock {{ get;
get; set;
set; }}
}}

27
Selecting Full Objects
 This example recaps how to query full objects
• Nothing new here 
private static void DemoFullObjectQueries(Product[] products)
private static void DemoFullObjectQueries(Product[] products)
{
{
Console.WriteLine("Low-stock
Console.WriteLine("Low-stock product
product details:");
details:");
var
var prods
prods == from
from pp in
in products
products
where
where p.InStock
p.InStock << 55
select p;
select p;
foreach (var p in prods)
foreach (var p in prods)
Console.WriteLine("\t{0}",
Console.WriteLine("\t{0}", p);
p);
}}

28
Selecting Specific Fields
 You can query specific fields from result objects
• Specify the required field in the select clause
private static void DemoSpecificFieldQueries(Product[] products)
private static void DemoSpecificFieldQueries(Product[] products)
{
{
Console.WriteLine("\nLow-stock
Console.WriteLine("\nLow-stock product
product prices:");
prices:");
var
var prices
prices == from
from pp in
in products
products
where
where p.InStock
p.InStock << 55
select p.Price;
select p.Price;
foreach (var p in prices)
foreach (var p in prices)
Console.WriteLine("\t{0:c}",
Console.WriteLine("\t{0:c}", p);
p);
}}

29
Selecting Projections
 You can query "projections" from result objects
• A projection is an anonymous type
• Contains the properties specified in the select clause
private static void DemoProjectionQueries(Product[] products)
private static void DemoProjectionQueries(Product[] products)
{
{
Console.WriteLine("\nLow-stock products and prices:");
Console.WriteLine("\nLow-stock products and prices:");
var projs = from p in products
var projs = from p in products
where p.InStock < 5
where p.InStock < 5
select
select new
new {{ p.Description,
p.Description, p.Price
p.Price };
};
foreach (var p in projs)
foreach (var p in projs)
Console.WriteLine("\t{0}, {1:c}", p.Description, p.Price);
Console.WriteLine("\t{0}, {1:c}", p.Description, p.Price);
}
}

30
Set-Based Operations (1 of 2)
 There are numerous extension methods that allow
you to perform set-based operations on queries
• Think "Venn-diagrams" 

 Set-based extension methods:


• Except()
• Intersect()
• Union()
• Concat()

 Additional useful extension methods:


• Count()
• Distinct()
• Reverse() 31
Set-Based Operations (2 of 2)
 These examples illustrate set-based operations
• … based on the following collections
List<string>
List<string> myTeams
myTeams == newnew List<String>
List<String> {{ "Swansea",
"Swansea", "Arsenal",
"Arsenal", "Liverpool",
"Liverpool", "Blackpool"
"Blackpool" };
};
List<string>
List<string> yourTeams
yourTeams == new
new List<String>
List<String> {{ "Swansea",
"Swansea", "Man
"Man Utd",
Utd", "West
"West Brom",
Brom", "Liverpool"
"Liverpool" };
};

// Teams I like but you don't…


// Teams I like but you don't…
var
var diff
diff == (from
(from tt in
in myTeams
myTeams select
select t).Except(from
t).Except(from t2
t2 in
in yourTeams
yourTeams select
select t2);
t2);

// Teams we both like…


// Teams we both like…
var
var intersect
intersect == (from
(from tt in
in myTeams
myTeams select
select t).Intersect(from
t).Intersect(from t2
t2 in
in yourTeams
yourTeams select
select t2);
t2);

//
// Teams
Teams either
either of
of us
us likes…
likes…
var
var union = (from t in myTeams
union = (from t in myTeams select
select t).Union(from
t).Union(from t2
t2 in
in yourTeams
yourTeams select
select t2);
t2);

// Concatenation of my teams and your teams…


// Concatenation of my teams and your teams…
var concat = (from t in myTeams select t).Concat(from t2 in yourTeams select t2);
var concat = (from t in myTeams select t).Concat(from t2 in yourTeams select t2);

//
// Distinct
Distinct concatenation
concatenation of
of my
my teams
teams and
and your
your teams…
teams…
var
var distinct = (from t in myTeams select t).Concat(from t2
distinct = (from t in myTeams select t).Concat(from t2 in
in yourTeams
yourTeams select
select t2)
t2)
.Distinct();
.Distinct();
32
Aggregate Operations
 LINQ provides various "aggregate" extension
methods
• Familiar concept for SQL developers 
private
private static
static void
void DemoAggregates()
DemoAggregates()
{{
double[] winterTemps = { 2.0, -3.3, 8, -4, 0, 8.2 };
double[] winterTemps = { 2.0, -3.3, 8, -4, 0, 8.2 };
Console.WriteLine("\nAggregate
Console.WriteLine("\nAggregate query
query results:");
results:");
Console.WriteLine("Max:
Console.WriteLine("Max: {0:f2}", (from tt in
{0:f2}", (from in winterTemps
winterTemps select
select t).Max());
t).Max());
Console.WriteLine("Min:
Console.WriteLine("Min: {0:f2}",
{0:f2}", (from
(from tt in
in winterTemps
winterTemps select
select t).Min());
t).Min());
Console.WriteLine("Avg: {0:f2}", (from t in winterTemps select t).Average());
Console.WriteLine("Avg: {0:f2}", (from t in winterTemps select t).Average());
Console.WriteLine("Sum:
Console.WriteLine("Sum: {0:f2}",
{0:f2}", (from
(from tt in
in winterTemps
winterTemps select
select t).Sum());
t).Sum());
}
}

33
Summary
 Introduction to LINQ
 Using LINQ with arrays
 Using LINQ with collections
 LINQ under the hood
 Additional LINQ techniques

34

You might also like