Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (438.53 KB, 45 trang )
<span class='text_page_counter'>(1)</span><div class='page_container' data-page=1>
System.Core.dll
System.Data.Linq.dll
System.Data.DataSetExtensions.dll
For now:
Dynamically-created string queries
Doesn't provide compile-time checking
Native code and non-native code is mixed
With LINQ
Static typing
Compile-time syntax checking
Type of the variable induced from expression
Must include initializer
Can’t be null. Why not?
What happens if “var” is a class in scope?
Works in for loops
<b>var i =</b> <b>5;</b>
<b>var s =</b> <b>"Hello";</b>
<b>var d =</b> <b>1.0;</b>
The Problem: How to add a method to a type you don’t control
and can’t subtype?
Example: How to add Standard Query Operators to
IEnumerable<T>, without deriving a new interface?
Solution: Extension methods aren’t really members of the target
type, but the syntax makes them look that way
Not for properties, events, operators
Currently under consideration
Equivalent to calling the static method
Difference from actually extending the class?
How could we use this for Polynomials?
Disadvantages?
Implicitness
Define a Static Class
Define a static method whose first argument is an object of type
T
[System.Runtime.CompilerServices.Extension] attribute on first
C# binds the attribute to keyword “this”
Create a T object, and call the method as if it were a member of
the object
Extension Methods have lower priority of resolution than type
members
So if a type has a member with same signature as a LINQ
extension method, the type’s member will be called, and there is
no ambiguity
<b>public</b> <b>IEnumerable<int></b> <b>Where(</b>
<b>Func<int,bool></b> <b>filter) {</b>
<b>// LINQ queries on MyList objects will call this</b>
<b>// instead of Sequence.Where()</b>
Lambda Expressions
Generalized function syntax
x . x + 1
in C# 3.0, have x => x + 1
From anonymous delegate syntax:
delegate(int x) { return x + 1;}
Can have implicitly typed variables
Can have more than one variable
Can have expression or statement body
Lambda expressions
Can be converted to delegate type
if parameters and body match
Participate in type inference
If expression body, get expression trees
<b>delegate</b> <b>R Func<A,R>(A arg);</b>
<b>Func<int,int></b> <b>f1 =</b> <b>x =></b> <b>x +</b> <b>1;</b>
<b>Func<int,double></b> <b>f2 =</b> <b>x =></b> <b>x +</b> <b>1;</b>
Lambda expressions
Type inference
If call Select(customers, c => c.Name);
T, S mapped to appropriate types
<b>public</b> <b>static</b> <b>IEnumerable<S></b> <b>Select<T,S>(</b>
<b>this</b> <b>IEnumerable<T></b> <b>source,</b>
<b>Func<T,S></b> <b>selector)</b>
<b>{</b>
<b>foreach</b> <b>(T element in</b> <b>source)</b>
<b>yield return</b> <b>selector(element);</b>
<b>class</b> <b>Car</b>
<b>{</b>
<b>public</b> <b>string</b> <b>PetName =</b> <b>string.Empty;</b>
<b>public</b> <b>string</b> <b>Color =</b> <b>string.Empty;</b>
<b>public</b> <b>int</b> <b>Speed;</b>
<b>public</b> <b>string</b> <b>Make =</b> <b>string.Empty;</b>
<b>}</b>
List<ItemType>
Dictionary<K,V>
Stack<ItemType>
Queue<ItemType>
IList<ItemType>
IDictionary<K,V>
ICollection<ItemType>
IEnumerable<ItemType>
IEnumerator<ItemType>
<b>static void</b> <b>GetFastCars(List<Car></b> <b>myCars)</b>
<b>{</b>
<b>// Create a query expression.</b>
<b>var fastCars =</b> <b>from c in</b> <b>myCars where c.Speed ></b> <b>55</b> <b>select c;</b>
<b>foreach</b> <b>(var car in</b> <b>fastCars)</b>
<b>{</b>
<b>Console.WriteLine("{0} is going too fast!",</b> <b>car.PetName);</b>
<b>// Extract the ints from the ArrayList.</b>
<b>ArrayList myStuff =</b> <b>new</b> <b>ArrayList();</b>
<b>myStuff.AddRange(new object[] {</b> <b>10,</b> <b>400,</b> <b>8,</b> <b>false,</b> <b>new</b> <b>Car(),</b>
<b>"string data"</b> <b>});</b>
<b>IEnumerable<int></b> <b>myInts =</b> <b>myStuff.OfType<int>();</b>
<b>// Prints out 10, 400, and 8.</b>
<b>{</b>
<b>Console.WriteLine("***** LINQ over ArrayList *****\n");</b>
<b>// Here is a nongeneric collection of cars.</b>
<b>ArrayList myCars =</b> <b>new</b> <b>ArrayList() {</b>
<b>new</b> <b>Car{</b> <b>PetName =</b> <b>"Henry",</b> <b>Color =</b> <b>"Silver",</b> <b>Speed =</b> <b>100,</b> <b>Make </b>
<b>=</b> <b>"BMW"},</b>
<b>new</b> <b>Car{</b> <b>PetName =</b> <b>"Daisy",</b> <b>Color =</b> <b>"Tan",</b> <b>Speed =</b> <b>90,</b> <b>Make =</b>
<b>"BMW"},</b>
<b>new</b> <b>Car{</b> <b>PetName =</b> <b>"Mary",</b> <b>Color =</b> <b>"Black",</b> <b>Speed =</b> <b>55,</b> <b>Make =</b>
<b>"VW"},</b>
<b>new</b> <b>Car{</b> <b>PetName =</b> <b>"Clunker",</b> <b>Color =</b> <b>"Rust",</b> <b>Speed =</b> <b>5,</b> <b>Make =</b>
<b>"Yugo"},</b>
Adds querying to language
Important for interaction with DB
Built-in data structures
Leave query planning to data structure designer
Implemented using above functionality
Anonymous types and variables useful
As with collections:
not an interface
just need to implement the methods
necessary for backwards compatibility
methods may be implemented by extension
Methods named as above
Any class that implements pattern can be accessed via the new
<b>static void</b> <b>QueryStringWithOperators()</b>
<b>{</b>
<b>Console.WriteLine("***** Using Query Operators *****");</b>
<b>string[]</b> <b>currentVideoGames = {"Morrowind",</b> <b>"BioShock",</b>
<b>"Half Life 2: Episode 1",</b> <b>"The Darkness",</b>
<b>"Daxter",</b> <b>"System Shock 2"};</b>
<b>// Build a query expression using query operators.</b>
<b>var subset =</b> <b>from g in</b> <b>currentVideoGames</b>
<b>where g.Length ></b> <b>6</b> <b>orderby g select g;</b>
Building a LINQ query expression using the methods of the
Enumerable type directly is much more verbose than making use of
the C# query operators
<b>static void</b> <b>QueryStringsWithEnumerableAndLambdas()</b>
<b>{</b>
<b>string[]</b> <b>currentVideoGames = {"Morrowind",</b> <b>"BioShock",</b>
<b>"Daxter",</b> <b>"System Shock 2"};</b>
<b>// Build a query expression using extension methods</b>
<b>// granted to the Array via the Enumerable type.</b>
<b>var subset =</b> <b>currentVideoGames.Where(game =></b> <b>game.Length ></b> <b>6)</b>
<b>.OrderBy(game =></b> <b>game).Select(game =></b> <b>game);</b>
<b>// Print out the results.</b>
<b>foreach</b> <b>(var game in</b> <b>subset)</b>
<b>Console.WriteLine("Item: {0}",</b> <b>game);</b>
<b>{</b>
<b>Console.WriteLine("***** Using Anonymous Methods *****");</b>
<b>string[]</b> <b>currentVideoGames = {"Morrowind",</b> <b>"BioShock",</b>
<b>"Half Life 2: Episode 1",</b> <b>"The Darkness",</b>
<b>"Daxter",</b> <b>"System Shock 2"};</b>
<b>// Build the necessary Func<> delegates using anonymous methods.</b>
<b>Func<string,</b> <b>bool></b> <b>searchFilter =</b>
<b>delegate(string</b> <b>game) {</b> <b>return</b> <b>game.Length ></b> <b>6; };</b>
<b>Func<string,</b> <b>string></b> <b>itemToProcess =</b> <b>delegate(string</b> <b>s) {</b>
<b>return</b> <b>s; };</b>
<b>// Pass the delegates into the methods of Enumerable.</b>
<b>var subset =</b> <b>currentVideoGames.Where(searchFilter)</b>
<b>.OrderBy(itemToProcess).Select(itemToProcess);</b>
<b>class</b> <b>VeryComplexQueryExpression</b>
<b>{</b>
<b>public</b> <b>static void</b> <b>QueryStringsWithRawDelegates()</b>
<b>{</b>
<b>Console.WriteLine("***** Using Raw Delegates *****");</b>
<b>string[]</b> <b>currentVideoGames = {"Morrowind",</b> <b>"BioShock",</b>
<b>"Half Life 2: Episode 1",</b> <b>"The Darkness",</b>
<b>"Daxter",</b> <b>"System Shock 2"};</b>
<b>// Build the necessary Func<> delegates using anonymous methods.</b>
<b>Func<string,</b> <b>bool></b> <b>searchFilter =</b> <b>new</b> <b>Func<string,</b> <b>bool>(Filter);</b>
<b>Func<string,</b> <b>string></b> <b>itemToProcess =</b> <b>new</b>
<b>Func<string,string>(ProcessItem);</b>
<b>// Pass the delegates into the methods of Enumerable.</b>
<b>var subset =</b> <b>currentVideoGames</b>
<b>.Where(searchFilter).OrderBy(itemToProcess).Select(itemToProcess);</b>
<b>// Print out the results.</b>
<b>foreach</b> <b>(var game in</b> <b>subset)</b>
<b>Console.WriteLine("Item: {0}",</b> <b>game);</b>
<b>Console.WriteLine();</b>
<b>}</b>
<b>Operators</b> <b>Meaning in Life</b>
from, in
Used to define the backbone for any LINQ expression,
which allows you to extract a subset of data from a
fitting container.
where Used to define a restriction for which items to extract
from a container
select Used to select a sequence from the container
join, on, equals, into
<b>class</b> <b>Car</b>
<b>{</b>
<b>public</b> <b>string</b> <b>PetName =</b> <b>string.Empty;</b>
<b>public</b> <b>string</b> <b>Color =</b> <b>string.Empty;</b>
<b>public</b> <b>int</b> <b>Speed;</b>
<b>public</b> <b>string</b> <b>Make =</b> <b>string.Empty;</b>
<b>public override</b> <b>string</b> <b>ToString()</b>
<b>{</b>
<b>return</b> <b>string.Format("Make={0}, Color={1}, Speed={2}, PetName={3}",</b>
<b>Make,</b> <b>Color,</b> <b>Speed,</b> <b>PetName);</b>
<b>}</b>
<b>}</b>
<b>static void</b> <b>Main(string[]</b> <b>args)</b>
<b>{</b>
<b>Console.WriteLine("***** Fun with Query Expressions *****\n");</b>
<b>// This array will be the basis of our testing...</b>
<b>Car[]</b> <b>myCars =</b> <b>new</b> <b>[] {</b>
<b>new</b> <b>Car{</b> <b>PetName =</b> <b>"Henry",</b> <b>Color =</b> <b>"Silver",</b> <b>Speed =</b> <b>100,</b> <b>Make =</b> <b>"BMW"},</b>
<b>new</b> <b>Car{</b> <b>PetName =</b> <b>"Daisy",</b> <b>Color =</b> <b>"Tan",</b> <b>Speed =</b> <b>90,</b> <b>Make =</b> <b>"BMW"},</b>
<b>new</b> <b>Car{</b> <b>PetName =</b> <b>"Mary",</b> <b>Color =</b> <b>"Black",</b> <b>Speed =</b> <b>55,</b> <b>Make =</b> <b>"VW"},</b>
<b>new</b> <b>Car{</b> <b>PetName =</b> <b>"Clunker",</b> <b>Color =</b> <b>"Rust",</b> <b>Speed =</b> <b>5,</b> <b>Make =</b> <b>"Yugo"},</b>
<b>new</b> <b>Car{</b> <b>PetName =</b> <b>"Hank",</b> <b>Color =</b> <b>"Tan",</b> <b>Speed =</b> <b>0,</b> <b>Make =</b> <b>"Ford"},</b>
<b>new</b> <b>Car{</b> <b>PetName =</b> <b>"Sven",</b> <b>Color =</b> <b>"White",</b> <b>Speed =</b> <b>90,</b> <b>Make =</b> <b>"Ford"},</b>
<b>new</b> <b>Car{</b> <b>PetName =</b> <b>"Mary",</b> <b>Color =</b> <b>"Black",</b> <b>Speed =</b> <b>55,</b> <b>Make =</b> <b>"VW"},</b>
<b>new</b> <b>Car{</b> <b>PetName =</b> <b>"Zippy",</b> <b>Color =</b> <b>"Yellow",</b> <b>Speed =</b> <b>55,</b> <b>Make =</b> <b>"VW"},</b>
<b>new</b> <b>Car{</b> <b>PetName =</b> <b>"Melvin",</b> <b>Color =</b> <b>"White",</b> <b>Speed =</b> <b>43,</b> <b>Make =</b> <b>"Ford"}</b>
<b>};</b>
<b>static void</b> <b>BasicSelection(Car[]</b> <b>myCars)</b>
<b>{</b>
<b>// Get everything.</b>
<b>Console.WriteLine("All cars:");</b>
<b>var allCars =</b> <b>from c in</b> <b>myCars select c;</b>
<b>foreach</b> <b>(var c in</b> <b>allCars)</b>
<b>{</b>
<b>Console.WriteLine(c.ToString());</b>
<b>}</b>
<b>static void</b> <b>GetSubsets(Car[]</b> <b>myCars)</b>
<b>{</b>
<b>// Now get only the BMWs.</b>
<b>var onlyBMWs =</b> <b>from c in</b> <b>myCars where c.Make ==</b>
<b>"BMW"</b> <b>select c;</b>
<b>var makesColors =</b> <b>from c in</b> <b>myCars select new</b> <b>{c.Make,</b>
<b>c.Color};</b>
<b>foreach</b> <b>(var o in</b> <b>makesColors)</b>
<b>{</b>
<b>static void</b> <b>ReversedSelection(Car[]</b> <b>myCars)</b>
<b>{</b>
<b>// Get everything in reverse.</b>
<b>Console.WriteLine("All cars in reverse:");</b>
<b>var subset = (from c in</b> <b>myCars select </b>
<b>c).Reverse<Car>();</b>
<b>foreach</b> <b>(Car c in</b> <b>subset)</b>
<b>{</b>
<b>Console.WriteLine("{0} is going {1} </b>
<b>MPH",</b> <b>c.PetName,</b> <b>c.Speed);</b>
A query expression can take an orderby operator to sort items in the subset by a
specific value
To view the results in a descending order, simply include the descending operator
Example
1. static void OrderedResults(Car[] myCars)
2. {
3. // Order all the cars by PetName.
4. var subset = from c in myCars orderby c.PetName select c;
5. Console.WriteLine("Ordered by PetName:");
6. foreach (Car c insubset)
7. {
8. Console.WriteLine(c.ToString());
9. }
10. // Now find the cars that are going less than 55 mph,
11. // and order by descending PetName
12. subset = from c in myCars
13. where c.Speed > 55 orderby c.PetName descending select c;
14. Console.WriteLine("\nCars going faster than 55, ordered by PetName:");
15. foreach (Car c insubset)
16. {
17. Console.WriteLine(c.ToString());
18. }
<b>obtaining a result set that determines the differences between </b>
<i><b>two IEnumerable<T> compatible containers</b></i>
static void GetDiff()
{
List<string> myCars = new List<String>
{ "Yugo", "Aztec", "BMW"};
List<string> yourCars = new List<String>
{ "BMW", "Saab", "Aztec" };
var carDiff =(from c in myCars select c)
.Except(from c2 in yourCars select c2);
Console.WriteLine("Here is what you don't have, but I do:");
foreach (string s in carDiff)
Console.WriteLine(s); // Prints Yugo.