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 have to construct SQL strings.
• PHP example:
if (some_condition()) {
$q = mysql_query(“select name from user were id = $id”)
...
}
• When will the problem be detected?
2
3
Searching in Collections
• Begin with a simple array of, say,
Customers.
Customer[] customers = new Customer[30];
customers[0] = new Customer(…);
…
customers[29] = new Customer(…);
4
Searching in Collections:
The Old Way
• Find the names of all London customers:
List<string> londoners = new List<string>();
foreach (Customer c in customers) {
if (c.City == “London”) {
londoners.add(c.Name);
}
}
5
Searching in Collections:
The LINQ Way
string[] londoners =
from c in customers
where c.City == “London”
select c.Name;
Declarative!
SQL-like!
No loops!
Returns a simple array!
Searching in Collections:
The LINQ Way
• LINQ is a C# feature
– Introduced in C# 3.0.
• LINQ = “Language INtegrated Query”
• So far, this is just list comprehension
added to C#.
• What did it take to add list
comprehension to the language?
7
LINQ: How Does It Work?
• LINQ syntax = shorthand for method
invocation.
• Syntactic sugar, using “Translation
maps”
8
Syntax Translation Example
string[] londoners =
from c in customers
where c.City == “London”
select c.Name;
string[] londoners =
customers.
Where(expression).
Select(expression);
9
Expressions == Methods?
• Where() wants a Boolean method.
• The method acts as a filter.
• Likewise for Select(): a translation
method.
10
Translating Expressions
• Problem: Translating
“c.City == “London””
to a boolean expression e, such that
Where(e) is valid?
11
C# Delegates
• C# delegates: method pointers.
• Since C# 1.0.
class Demo {
delegate void Foo();
void Bar() { … do something … };
void Test() {
Foo myDelegate = new Foo(Bar);
// “pointer” to Bar()
myDelegate(); // invoke
}
}
12
Delegates as Arguments
• Delegates can be passed as
arguments.
– Event handlers, jobs for threads, etc.
class Demo {
void Job() { … the job to carry out … };
void Test() {
Thread worker = new Thread(
new ThreadStart(Job));
worker.start();
}
}
13
Anonymous Methods
• Nameless methods = on-the-fly
delegates:
class Demo {
delegate void Foo();
void Test() {
Foo myDelegate = delegate() {
… do something …
};
myDelegate(); // invoke
}
}
14
Syntax Translation Example
string[] londoners =
from c in customers
where c.City == “London”
select c.Name;
string[] londoners =
customers.
Where(delegate(Customer c) {
return c.City == “London”; }).
Select(delegate(Customer c) {
return c.Name });
15
Well, Not Really.
•Where(), etc. accept delegate
methods.
• But LINQ creates lambda
expressions.
• Seamless conversion via
coercion.
16
Syntax Translation Example
string[] londoners =
from c in customers
where c.City == “London”
select c.Name;
string[] londoners =
customers.
Where(c => c.City == “London”).
Select(c => c.Name);
17
Lambda Expressions
• Lambda expression syntax:
(argumentList) => expression
oneArgument => expression
• Arguments optionally typed.
– Type inference mechanism.
– More on that later…
Shades of ML…
18
Where’s Where()?
• We invoked Where() on
Customers[].
• On the resulting Customers[], we
invoked Select().
• New methods for arrays!?
19
Extension Methods
class Utils {
public static firstChar(this string s)
{
return s.charAt(0);
}
}
• So far, just a simple static method.
• Can be used like any other.
20
Extension Methods
• But now…
Using Utils;
class Demo {
void Foo() {
string s = “Hello”;
Console.WriteLine(s.firstChar());
}
}
21
Extension Methods
• Static methods that seem to extend
existing types.
• Where(), Select(), etc. extend array
types in this manner.
22
Query Your Own Types!
• LINQ can be applied to any type,
not just built-in arrays and lists.
• Just implement Where(),
Select(), etc.
23
LINQ and Relational Data
• Let’s obtain a DB-table type, and query it.
DbCustomers customers = new DbCustomers(“my.mdb”);
string[] londoners =
from c in customers
where c.City == “London”
select c.Name;
24
This Makes No Sense!
• But… Where() applies the filter to
every record.
• … on the client!
• SELECT * FROM CUSTOMERS, and
filter with a simple loop!?
25
Back To Lambda
Expressions
• Lambda expressions can be
converted to anonymous methods.
• Can also be coerced to expression
trees.
– A run-time representation of the
syntax tree.
26
Example…
• Our code yields:
string[] londoners = customers.
Where(c => c.City == “London”).
Select(c => c.Name);
where “customers” is of type DbCustomers.
• No
DbCustomers.Where(delegate(Customer c))
method exists.
• However:
DbCustomers.Where(
Expression<Func<Customer,bool>> xt)
27
What Are Expression Trees?
• Any valid expression is converted by the
compiler to an expression tree.
– a.k.a. the abstract syntax tree of the expression.
– Normal part of the compilation process, in any language!
• Examples:
5 + 3 * 2 c.city == “London”
+
5 *
3 2
==
. (dot) “London”
c city
28
Expression Trees
• Normally, expression trees only exist at
compile-time.
• In C#, the compiler can create a run-time
representation of the expression tree.
– The language has a data type for expression trees.
– Represents lambda expressions at runtime.
• Used for generating SQL at runtime.
– Guaranteed to be syntactically valid, since it
was created from a valid C# expression.
It’s Just Coercion
• So, LINQ converts into expressions that
use Where(...), Select(...), etc.
• For some classes, Where(...) and
Select(...) accept delegates; for other
classes, they accept expression trees.
• Lambda expressions can be coerced
into either.
29
30
Projections
• Using LINQ’s select:
from c in customers
where c.City == “London”
select
new AddressBookEntry(c.Name, c.Phone);
31
Pre-Defined Types Only?
• But…
The projection type (e.g.,
AddressBookEntry) must be pre-
defined!
32
Ad-Hoc Types
• new { [name1 =] expr1,…, [ namen =] exprn}
• Type implied by types of exprs.
• Example:
from c in customers
where c.City == “London”
select new { c.Name, c.Phone };
If name is not specified, and
expr is either property or
x.property, then property’s
name will be used.
33
Ad-Hoc Types are Nameless
• How do we store the result?
??? q = from … select new {…};
• The ad-hoc type is nameless!
34
Auto-Typed Variables
• var x = 7; // x will be of type int
• var q = from … select new {…};
// q will be an array of the anonymous type
Console.WriteLine(q[0].Name);
• Local variables only.
– No auto-typing for fields or formal parameters.
Summary
• LINQ adds static SQL expression
correctness to C#.
• To do this, the following features were
added to C#:
– Lambda expressions.
– Extension methods.
– Expression types.
– List comprehension.
– Anonymous data types.
– Type inference.
35
There’s More
• There are several LINQ features we did
not present here, such as:
– Grouping (“GROUP BY” in SQL)
– Joins (selecting from multiple tables)
– ...
• These require even more language
features, such as closures.
36
What Is Happening to Languages?
• As new features are added to programming
languages, the languages evolve.
• Many of the features come from research or
experimental languages.
• Note how many of the new C# features
discussed here come from functional
languages like ML, Haskell or LISP:
– Lambda expressions, expression types, list
comprehension, anonymous data types, type
inference...
37
“Confessions of a Used Programming
Language Salesman”
• An 2007 essay by Eric Meijer (Microsoft).
• Discusses how features from functional
languages slowly creep into “mainstream”
languages.
• “Functional programming has finally reached
the masses, except that it is called Visual
Basic 9 instead of Haskell 98”.
38
A Glimpse Into the Future:
LISP (1958)
• We have seen the power of representing
program source at runtime (expression
trees).
• In LISP, program source can be
represented at runtime, but also generated
at runtime (or compile-time).
– Source code itself is a data structure (a list).
• LISP macros are light-years ahead of
C/C++ macros.
39
A Glimpse Into the Future:
LISP (1958)
• 50 years later, LISP features are slowly
re-appearing in mainstream languages.
– e.g., garbage collection, aspect-oriented
programming, and more.
• Conclusions:
– a. Learn from history.
– b. Know LISP, Haskell, etc: once you really
understand them, it will give you serious
advantages over ignorant software engineers
(even if you never use these languages in
practice).
40

linq with Exampls

  • 1.
    Putting it alltogether: LINQ as an Example The Problem: SQL in Code • Programs often connect to database servers. • Database servers only “speak” SQL. • Programs have to construct SQL strings. • PHP example: if (some_condition()) { $q = mysql_query(“select name from user were id = $id”) ... } • When will the problem be detected? 2
  • 2.
    3 Searching in Collections •Begin with a simple array of, say, Customers. Customer[] customers = new Customer[30]; customers[0] = new Customer(…); … customers[29] = new Customer(…); 4 Searching in Collections: The Old Way • Find the names of all London customers: List<string> londoners = new List<string>(); foreach (Customer c in customers) { if (c.City == “London”) { londoners.add(c.Name); } }
  • 3.
    5 Searching in Collections: TheLINQ Way string[] londoners = from c in customers where c.City == “London” select c.Name; Declarative! SQL-like! No loops! Returns a simple array! Searching in Collections: The LINQ Way • LINQ is a C# feature – Introduced in C# 3.0. • LINQ = “Language INtegrated Query” • So far, this is just list comprehension added to C#. • What did it take to add list comprehension to the language?
  • 4.
    7 LINQ: How DoesIt Work? • LINQ syntax = shorthand for method invocation. • Syntactic sugar, using “Translation maps” 8 Syntax Translation Example string[] londoners = from c in customers where c.City == “London” select c.Name; string[] londoners = customers. Where(expression). Select(expression);
  • 5.
    9 Expressions == Methods? •Where() wants a Boolean method. • The method acts as a filter. • Likewise for Select(): a translation method. 10 Translating Expressions • Problem: Translating “c.City == “London”” to a boolean expression e, such that Where(e) is valid?
  • 6.
    11 C# Delegates • C#delegates: method pointers. • Since C# 1.0. class Demo { delegate void Foo(); void Bar() { … do something … }; void Test() { Foo myDelegate = new Foo(Bar); // “pointer” to Bar() myDelegate(); // invoke } } 12 Delegates as Arguments • Delegates can be passed as arguments. – Event handlers, jobs for threads, etc. class Demo { void Job() { … the job to carry out … }; void Test() { Thread worker = new Thread( new ThreadStart(Job)); worker.start(); } }
  • 7.
    13 Anonymous Methods • Namelessmethods = on-the-fly delegates: class Demo { delegate void Foo(); void Test() { Foo myDelegate = delegate() { … do something … }; myDelegate(); // invoke } } 14 Syntax Translation Example string[] londoners = from c in customers where c.City == “London” select c.Name; string[] londoners = customers. Where(delegate(Customer c) { return c.City == “London”; }). Select(delegate(Customer c) { return c.Name });
  • 8.
    15 Well, Not Really. •Where(),etc. accept delegate methods. • But LINQ creates lambda expressions. • Seamless conversion via coercion. 16 Syntax Translation Example string[] londoners = from c in customers where c.City == “London” select c.Name; string[] londoners = customers. Where(c => c.City == “London”). Select(c => c.Name);
  • 9.
    17 Lambda Expressions • Lambdaexpression syntax: (argumentList) => expression oneArgument => expression • Arguments optionally typed. – Type inference mechanism. – More on that later… Shades of ML… 18 Where’s Where()? • We invoked Where() on Customers[]. • On the resulting Customers[], we invoked Select(). • New methods for arrays!?
  • 10.
    19 Extension Methods class Utils{ public static firstChar(this string s) { return s.charAt(0); } } • So far, just a simple static method. • Can be used like any other. 20 Extension Methods • But now… Using Utils; class Demo { void Foo() { string s = “Hello”; Console.WriteLine(s.firstChar()); } }
  • 11.
    21 Extension Methods • Staticmethods that seem to extend existing types. • Where(), Select(), etc. extend array types in this manner. 22 Query Your Own Types! • LINQ can be applied to any type, not just built-in arrays and lists. • Just implement Where(), Select(), etc.
  • 12.
    23 LINQ and RelationalData • Let’s obtain a DB-table type, and query it. DbCustomers customers = new DbCustomers(“my.mdb”); string[] londoners = from c in customers where c.City == “London” select c.Name; 24 This Makes No Sense! • But… Where() applies the filter to every record. • … on the client! • SELECT * FROM CUSTOMERS, and filter with a simple loop!?
  • 13.
    25 Back To Lambda Expressions •Lambda expressions can be converted to anonymous methods. • Can also be coerced to expression trees. – A run-time representation of the syntax tree. 26 Example… • Our code yields: string[] londoners = customers. Where(c => c.City == “London”). Select(c => c.Name); where “customers” is of type DbCustomers. • No DbCustomers.Where(delegate(Customer c)) method exists. • However: DbCustomers.Where( Expression<Func<Customer,bool>> xt)
  • 14.
    27 What Are ExpressionTrees? • Any valid expression is converted by the compiler to an expression tree. – a.k.a. the abstract syntax tree of the expression. – Normal part of the compilation process, in any language! • Examples: 5 + 3 * 2 c.city == “London” + 5 * 3 2 == . (dot) “London” c city 28 Expression Trees • Normally, expression trees only exist at compile-time. • In C#, the compiler can create a run-time representation of the expression tree. – The language has a data type for expression trees. – Represents lambda expressions at runtime. • Used for generating SQL at runtime. – Guaranteed to be syntactically valid, since it was created from a valid C# expression.
  • 15.
    It’s Just Coercion •So, LINQ converts into expressions that use Where(...), Select(...), etc. • For some classes, Where(...) and Select(...) accept delegates; for other classes, they accept expression trees. • Lambda expressions can be coerced into either. 29 30 Projections • Using LINQ’s select: from c in customers where c.City == “London” select new AddressBookEntry(c.Name, c.Phone);
  • 16.
    31 Pre-Defined Types Only? •But… The projection type (e.g., AddressBookEntry) must be pre- defined! 32 Ad-Hoc Types • new { [name1 =] expr1,…, [ namen =] exprn} • Type implied by types of exprs. • Example: from c in customers where c.City == “London” select new { c.Name, c.Phone }; If name is not specified, and expr is either property or x.property, then property’s name will be used.
  • 17.
    33 Ad-Hoc Types areNameless • How do we store the result? ??? q = from … select new {…}; • The ad-hoc type is nameless! 34 Auto-Typed Variables • var x = 7; // x will be of type int • var q = from … select new {…}; // q will be an array of the anonymous type Console.WriteLine(q[0].Name); • Local variables only. – No auto-typing for fields or formal parameters.
  • 18.
    Summary • LINQ addsstatic SQL expression correctness to C#. • To do this, the following features were added to C#: – Lambda expressions. – Extension methods. – Expression types. – List comprehension. – Anonymous data types. – Type inference. 35 There’s More • There are several LINQ features we did not present here, such as: – Grouping (“GROUP BY” in SQL) – Joins (selecting from multiple tables) – ... • These require even more language features, such as closures. 36
  • 19.
    What Is Happeningto Languages? • As new features are added to programming languages, the languages evolve. • Many of the features come from research or experimental languages. • Note how many of the new C# features discussed here come from functional languages like ML, Haskell or LISP: – Lambda expressions, expression types, list comprehension, anonymous data types, type inference... 37 “Confessions of a Used Programming Language Salesman” • An 2007 essay by Eric Meijer (Microsoft). • Discusses how features from functional languages slowly creep into “mainstream” languages. • “Functional programming has finally reached the masses, except that it is called Visual Basic 9 instead of Haskell 98”. 38
  • 20.
    A Glimpse Intothe Future: LISP (1958) • We have seen the power of representing program source at runtime (expression trees). • In LISP, program source can be represented at runtime, but also generated at runtime (or compile-time). – Source code itself is a data structure (a list). • LISP macros are light-years ahead of C/C++ macros. 39 A Glimpse Into the Future: LISP (1958) • 50 years later, LISP features are slowly re-appearing in mainstream languages. – e.g., garbage collection, aspect-oriented programming, and more. • Conclusions: – a. Learn from history. – b. Know LISP, Haskell, etc: once you really understand them, it will give you serious advantages over ignorant software engineers (even if you never use these languages in practice). 40