1. Trang chủ
  2. » Công Nghệ Thông Tin

Apress pro LINQ Language Integrated Query in C# 2008 phần 4 ppt

58 377 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 58
Dung lượng 1,02 MB

Nội dung

160 CHAPTER 5 ■ NONDEFERRED OPERATORS This code is functionally equivalent to the previous example. Instead of calling the Where operator to ensure a single element is in the sequence, I can provide the same sequence filtering operation in the Single operator itself. This should return the only element in the input sequence whose id is 3. Here are the results: Anders Hejlsberg Remember, if either prototype of the Single operator ends up with no element to return, an InvalidOperationException is thrown. To avoid this, use the SingleOrDefault operator. SingleOrDefault The SingleOrDefault operator is similar to the Single operator except for how it behaves when an element is not found. Prototypes There are two prototypes I cover. The First SingleOrDefault Prototype public static T SingleOrDefault<T>( this IEnumerable<T> source); This version of the prototype returns the only element found in the input sequence. If the sequence is empty, default(T) is returned. For reference and nullable types, the default value is null. If more than one element is found, an InvalidOperationException is thrown. The second prototype of the SingleOrDefault operator allows you to pass a predicate to deter- mine which element should be returned. The Second SingleOrDefault Prototype public static T SingleOrDefault<T>( this IEnumerable<T> source, Func<T, bool> predicate); Exceptions ArgumentNullException is thrown if any arguments are null. InvalidOperationException is thrown if the operator finds more than one element for which the predicate returns true. Examples Listing 5-30 is an example of the first SingleOrDefault prototype where no element is found. I have to get an empty sequence to do this. I’ll use the Where operator and provide a key comparison for a key that doesn’t exist for this purpose. Rattz_789-3.book Page 160 Tuesday, October 16, 2007 2:21 PM CHAPTER 5 ■ NONDEFERRED OPERATORS 161 Listing 5-30. Calling the First SingleOrDefault Prototype Where an Element Is Not Found Employee emp = Employee.GetEmployeesArray() .Where(e => e.id == 5).SingleOrDefault(); Console.WriteLine(emp == null ? "NULL" : string.Format("{0} {1}", emp.firstName, emp.lastName)); I queried for the employee whose id is 5 since I know none exists, so an empty sequence will be returned. Unlike the Single operator, the SingleOrDefault operator handles empty sequences just fine. Here are the results: NULL Listing 5-31 is the same example where a single element is found. I use the Where operator to provide a sequence with just one element. Listing 5-31. Calling the First SingleOrDefault Prototype Where an Element Is Found Employee emp = Employee.GetEmployeesArray() .Where(e => e.id == 4).SingleOrDefault(); Console.WriteLine(emp == null ? "NULL" : string.Format("{0} {1}", emp.firstName, emp.lastName)); This time I specify an id I know exists. Here are the results for the code when an element is found: David Lightman As you can see, the employee has been found. For the second SingleOrDefault prototype, shown in Listing 5-32, I specify an id that I know exists. Instead of using the Where operator, I embed the filter into the SingleOrDefault operator call. Listing 5-32. Calling the Second SingleOrDefault Prototype Where an Element Is Found Employee emp = Employee.GetEmployeesArray() .SingleOrDefault(e => e.id == 4); Console.WriteLine(emp == null ? "NULL" : string.Format("{0} {1}", emp.firstName, emp.lastName)); This example is functionally equivalent to the previous example except instead of filtering the elements using the Where operator, I filter them by passing a predicate to the SingleOrDefault oper- ator. Here are the results: David Lightman Rattz_789-3.book Page 161 Tuesday, October 16, 2007 2:21 PM 162 CHAPTER 5 ■ NONDEFERRED OPERATORS Now I will try that with a predicate that will not find a match, as shown in Listing 5-33. Listing 5-33. Calling the Second LastOrDefault Prototype Where an Element Is Not Found Employee emp = Employee.GetEmployeesArray() .SingleOrDefault(e => e.id == 5); Console.WriteLine(emp == null ? "NULL" : string.Format("{0} {1}", emp.firstName, emp.lastName)); Since there is no element whose id is 5, no elements are found. Here are the results: NULL While no elements were found in the sequence, the SingleOrDefault operator handled the situation gracefully instead of throwing an exception. ElementAt The ElementAt operator returns the element from the source sequence at the specified index. Prototypes There is one prototype I cover. The ElementAt Prototype public static T ElementAt<T>( this IEnumerable<T> source, int index); If the sequence implements IList<T>, the IList interface is used to retrieve the indexed element directly. If the sequence does not implement IList<T>, the sequence is enumerated until the indexed element is reached. An ArgumentOutOfRangeException is thrown if the index is less than zero or greater than or equal to the number of elements in the sequence. ■Note In C#, indexes are zero-based. This means the first element’s index is zero. The last element’s index is the sequence’s count minus one. Exceptions ArgumentNullException is thrown if the source argument is null. ArgumentOutOfRangeException is thrown if the index is less than zero or greater than or equal to the number of elements in the sequence. Examples Listing 5-34 is an example calling the only prototype of the ElementAt operator. Rattz_789-3.book Page 162 Tuesday, October 16, 2007 2:21 PM CHAPTER 5 ■ NONDEFERRED OPERATORS 163 Listing 5-34. Calling the ElementAt Operator Employee emp = Employee.GetEmployeesArray() .ElementAt(3); Console.WriteLine("{0} {1}", emp.firstName, emp.lastName); I specified that I want the element whose index is 3, which is the fourth element. Here are the results of the query: David Lightman ElementAtOrDefault The ElementAtOrDefault operator returns the element from the source sequence at the specified index. Prototypes There is one prototype I cover. The ElementAtOrDefault Prototype public static T ElementAtOrDefault<T>( this IEnumerable<T> source, int index); If the sequence implements IList<T>, the IList interface is used to retrieve the indexed element directly. If the sequence does not implement IList<T>, the sequence will be enumerated until the indexed element is reached. If the index is less than zero or greater than or equal to the number of elements in the sequence, default(T) is returned. For reference and nullable types, the default value is null. This is the behavior that distinguishes it from the ElementAt operator. Exceptions ArgumentNullException is thrown if the source argument is null. Examples Listing 5-35 is an example calling the ElementAtOrDefault operator when the index is valid. Listing 5-35. Calling the ElementAtOrDefault Operator with a Valid Index Employee emp = Employee.GetEmployeesArray() .ElementAtOrDefault(3); Console.WriteLine(emp == null ? "NULL" : string.Format("{0} {1}", emp.firstName, emp.lastName)); Here are the results of the query: David Lightman Rattz_789-3.book Page 163 Tuesday, October 16, 2007 2:21 PM 164 CHAPTER 5 ■ NONDEFERRED OPERATORS Just as expected, the element at index 3 is retrieved. Now I will try a query with an invalid index using the code in Listing 5-36. Listing 5-36. Calling the ElementAtOrDefault Operator with an Invalid Index Employee emp = Employee.GetEmployeesArray() .ElementAtOrDefault(5); Console.WriteLine(emp == null ? "NULL" : string.Format("{0} {1}", emp.firstName, emp.lastName)); There is no element whose index is 5. Here are the results of the query: NULL Quantifiers The following quantifier operators allow you to perform quantification type operations on input sequences. Any The Any operator returns true if any element of an input sequence matches a condition. Prototypes There are two prototypes I cover. The First Any Prototype public static bool Any<T>( this IEnumerable<T> source); This prototype of the Any operator will return true if the source input sequence contains any elements. The second prototype of the Any operator enumerates the source input sequence and returns true if at least one element in the input sequence causes the predicate method delegate to return true. The source input sequence enumeration halts once the predicate returns true. The Second Any Prototype public static bool Any<T>( this IEnumerable<T> source, Func<T, bool> predicate); Exceptions ArgumentNullException is thrown if any of the arguments are null. Examples First I will try the case of an empty sequence, as shown in Listing 5-37. I will use the Empty operator I covered in the previous chapter. Rattz_789-3.book Page 164 Tuesday, October 16, 2007 2:21 PM CHAPTER 5 ■ NONDEFERRED OPERATORS 165 Listing 5-37. First Any Prototype Where No Elements Are in the Source Input Sequence bool any = Enumerable.Empty<string>().Any(); Console.WriteLine(any); Here are the results of this code: False Next I will try the same prototype but, this time, with elements in the input sequence, as shown in Listing 5-38. Listing 5-38. First Any Prototype Where Elements Are in the Source Input Sequence string[] presidents = { "Adams", "Arthur", "Buchanan", "Bush", "Carter", "Cleveland", "Clinton", "Coolidge", "Eisenhower", "Fillmore", "Ford", "Garfield", "Grant", "Harding", "Harrison", "Hayes", "Hoover", "Jackson", "Jefferson", "Johnson", "Kennedy", "Lincoln", "Madison", "McKinley", "Monroe", "Nixon", "Pierce", "Polk", "Reagan", "Roosevelt", "Taft", "Taylor", "Truman", "Tyler", "Van Buren", "Washington", "Wilson"}; bool any = presidents.Any(); Console.WriteLine(any); Here are the results of this code: True For the next example, I use the second prototype, first with no elements matching the predicate, as shown in Listing 5-39. Listing 5-39. Second Any Prototype Where No Elements Cause the Predicate to Return True string[] presidents = { "Adams", "Arthur", "Buchanan", "Bush", "Carter", "Cleveland", "Clinton", "Coolidge", "Eisenhower", "Fillmore", "Ford", "Garfield", "Grant", "Harding", "Harrison", "Hayes", "Hoover", "Jackson", "Jefferson", "Johnson", "Kennedy", "Lincoln", "Madison", "McKinley", "Monroe", "Nixon", "Pierce", "Polk", "Reagan", "Roosevelt", "Taft", "Taylor", "Truman", "Tyler", "Van Buren", "Washington", "Wilson"}; bool any = presidents.Any(s => s.StartsWith("Z")); Console.WriteLine(any); I specify that I want the presidents that start with the string "Z". Since there are none, an empty sequence will be returned causing the Any operator to return false. The results are as one would expect: False Rattz_789-3.book Page 165 Tuesday, October 16, 2007 2:21 PM 166 CHAPTER 5 ■ NONDEFERRED OPERATORS Finally, I try an example of the second prototype with a predicate that should return true for at least one element, as shown in Listing 5-40. Listing 5-40. Second Any Prototype Where at Least One Element Causes the Predicate to Return True string[] presidents = { "Adams", "Arthur", "Buchanan", "Bush", "Carter", "Cleveland", "Clinton", "Coolidge", "Eisenhower", "Fillmore", "Ford", "Garfield", "Grant", "Harding", "Harrison", "Hayes", "Hoover", "Jackson", "Jefferson", "Johnson", "Kennedy", "Lincoln", "Madison", "McKinley", "Monroe", "Nixon", "Pierce", "Polk", "Reagan", "Roosevelt", "Taft", "Taylor", "Truman", "Tyler", "Van Buren", "Washington", "Wilson"}; bool any = presidents.Any(s => s.StartsWith("A")); Console.WriteLine(any); And finally, here are the results: True All The All operator returns true if every element in the input sequence matches a condition. Prototypes There is one prototype I cover. The All Prototype public static bool All<T>( this IEnumerable<T> source, Func<T, bool> predicate); The All operator enumerates the source input sequence and returns true only if the predicate returns true for every element in the sequence. Once the predicate returns false, the enumeration will cease. Exceptions ArgumentNullException is thrown if any of the arguments are null. Examples In Listing 5-41 I begin with a predicate with which I know at least some of the elements will return false. Listing 5-41. All Prototype Where Not Every Element Causes the Predicate to Return True string[] presidents = { "Adams", "Arthur", "Buchanan", "Bush", "Carter", "Cleveland", "Clinton", "Coolidge", "Eisenhower", "Fillmore", "Ford", "Garfield", "Grant", "Harding", "Harrison", "Hayes", "Hoover", "Jackson", "Jefferson", "Johnson", "Kennedy", "Lincoln", "Madison", "McKinley", Rattz_789-3.book Page 166 Tuesday, October 16, 2007 2:21 PM CHAPTER 5 ■ NONDEFERRED OPERATORS 167 "Monroe", "Nixon", "Pierce", "Polk", "Reagan", "Roosevelt", "Taft", "Taylor", "Truman", "Tyler", "Van Buren", "Washington", "Wilson"}; bool all = presidents.All(s => s.Length > 5); Console.WriteLine(all); Since I know not every president in the array has a length of more than five characters, I know that predicate will return false for some elements. Here is the output: False Now I will try a case where I know every element will cause the predicate to return true, as shown in Listing 5-42. Listing 5-42. All Prototype Where Every Element Causes the Predicate to Return True string[] presidents = { "Adams", "Arthur", "Buchanan", "Bush", "Carter", "Cleveland", "Clinton", "Coolidge", "Eisenhower", "Fillmore", "Ford", "Garfield", "Grant", "Harding", "Harrison", "Hayes", "Hoover", "Jackson", "Jefferson", "Johnson", "Kennedy", "Lincoln", "Madison", "McKinley", "Monroe", "Nixon", "Pierce", "Polk", "Reagan", "Roosevelt", "Taft", "Taylor", "Truman", "Tyler", "Van Buren", "Washington", "Wilson"}; bool all = presidents.All(s => s.Length > 3); Console.WriteLine(all); Since I know every president’s name has at least four characters, the All operator should return true. Here is the output: True Contains The Contains operator returns true if any element in the input sequence matches the specified value. Prototypes There are two prototypes I cover. The First Contains Prototype public static bool Contains<T>( this IEnumerable<T> source, T value); This prototype of the Contains operator first checks the source input sequence to see if it imple- ments the ICollection<T> interface, and if it does, it calls the Contains method of the sequence’s implementation. If the sequence does not implement the ICollection<T> interface, it enumerates the source input sequence to see if any element matches the specified value. Once it finds an element that does match, the enumeration halts. Rattz_789-3.book Page 167 Tuesday, October 16, 2007 2:21 PM 168 CHAPTER 5 ■ NONDEFERRED OPERATORS The specified value is compared to each element using the EqualityComparer<K>.Default default equality comparison class. The second prototype is like the previous except an IEqualityComparer<T> object can be speci- fied. If this prototype is used, each element in the sequence is compared to the passed value using the passed equality comparison object. The Second Contains Prototype public static bool Contains<T>( this IEnumerable<T> source, T value, IEqualityComparer<T> comparer); Exceptions ArgumentNullException is thrown if the source input sequence is null. Examples For an example of the first prototype, I begin with a value that I know is not in my input sequence, as shown in Listing 5-43 Listing 5-43. First Contains Prototype Where No Element Matches the Specified Value string[] presidents = { "Adams", "Arthur", "Buchanan", "Bush", "Carter", "Cleveland", "Clinton", "Coolidge", "Eisenhower", "Fillmore", "Ford", "Garfield", "Grant", "Harding", "Harrison", "Hayes", "Hoover", "Jackson", "Jefferson", "Johnson", "Kennedy", "Lincoln", "Madison", "McKinley", "Monroe", "Nixon", "Pierce", "Polk", "Reagan", "Roosevelt", "Taft", "Taylor", "Truman", "Tyler", "Van Buren", "Washington", "Wilson"}; bool contains = presidents.Contains("Rattz"); Console.WriteLine(contains); Since there is no element whose value is "Rattz" in the array, the contains variable should be false. Here is the output: False In Listing 5-44, I know an element will match my specified value. Listing 5-44. First Contains Prototype Where an Element Matches the Specified Value string[] presidents = { "Adams", "Arthur", "Buchanan", "Bush", "Carter", "Cleveland", "Clinton", "Coolidge", "Eisenhower", "Fillmore", "Ford", "Garfield", "Grant", "Harding", "Harrison", "Hayes", "Hoover", "Jackson", "Jefferson", "Johnson", "Kennedy", "Lincoln", "Madison", "McKinley", "Monroe", "Nixon", "Pierce", "Polk", "Reagan", "Roosevelt", "Taft", "Taylor", "Truman", "Tyler", "Van Buren", "Washington", "Wilson"}; Rattz_789-3.book Page 168 Tuesday, October 16, 2007 2:21 PM CHAPTER 5 ■ NONDEFERRED OPERATORS 169 bool contains = presidents.Contains("Hayes"); Console.WriteLine(contains); Since there is an element with the value of "Hayes", the contains variable should be true. Here is the output: True For an example of the second Contains operator prototype, I will use my common MyStringifiedNumberComparer class. I will check an array of numbers in string format for a number in string format that is technically unequal to any element in the array, but because I use my equality comparison class, the appropriate element will be found. Listing 5-45 shows the example. Listing 5-45. Second Contains Prototype Where an Element Matches the Specified Value string[] stringifiedNums = { "001", "49", "017", "0080", "00027", "2" }; bool contains = stringifiedNums.Contains("0000002", new MyStringifiedNumberComparer()); Console.WriteLine(contains); Since I am looking for an element with a value of "0000002", and because my equality compar- ison object will be used, which will convert that string value as well as all of the sequence elements to an integer before making the comparison, and because my sequence contains the element "2", the contains variable should be true. Let’s take a look at the results: True Now I will try the same example except this time I will query for an element that I know doesn’t exist. The code is shown in Listing 5-46. Listing 5-46. Second Contains Prototype Where an Element Does Not Match the Specified Value string[] stringifiedNums = { "001", "49", "017", "0080", "00027", "2" }; bool contains = stringifiedNums.Contains("000271", new MyStringifiedNumberComparer()); Console.WriteLine(contains); Since I know that none of the elements when converted to an integer equals 271, I search the array for "000271". Here are the results: False Rattz_789-3.book Page 169 Tuesday, October 16, 2007 2:21 PM [...]... nullable, that is, int?, long?, double?, decimal?, a null is returned from the operator instead Examples In the example of the first Min prototype, shown in Listing 5-53, I declare an array of integers and return the minimum from it Listing 5-53 An Example of the First Min Prototype int[] myInts = new int[] { 9 74, 2, 7, 13 74, 27, 54 }; int minInt = myInts.Min(); Console.WriteLine(minInt); That is a pretty... NONDEFERRED OPERATORS Listing 5-57 An Example of the First Max Prototype int[] myInts = new int[] { 9 74, 2, 7, 13 74, 27, 54 }; int maxInt = myInts.Max(); Console.WriteLine(maxInt); The results are the following: 13 74 For an example of the second prototype, shown in Listing 5-58, I just call the Max operator on my standard presidents array Listing 5-58 An Example of the Second Max Prototype string[] presidents... of LINQ if the new XML API didn’t support LINQ queries In that vein, several new XML-specific query operators, implemented as extension methods, were added Combining these new XML-specific operators with the LINQ to Objects Standard Query Operators I discuss in Part 2 of this book creates a powerfully elegant solution for finding whatever data you are searching for in an XML tree Not only does LINQ. .. I will begin with an example of the first prototype, shown in Listing 5-51 First I generate a sequence of integers using the Range operator, and then I use the Sum operator to sum them Listing 5-51 An Example of the First Sum Prototype IEnumerable ints = Enumerable.Range(1, 10); foreach (int i in ints) Console.WriteLine(i); Console.WriteLine(" "); int sum = ints.Sum(); Console.WriteLine(sum);... to your project for the System.Xml .Linq assembly if it is not already present Referenced Namespaces The examples in this chapter use the System .Linq, System.Xml .Linq, and System.Collections Generic namespaces Therefore, you should add using directives for these namespaces to your code if they are not already present: using System .Linq; using System.Xml .Linq; using System.Collections.Generic; In addition... sound understanding of LINQ to Objects and just what LINQ can do for you, it’s time to learn about using LINQ to query and generate XML This functionality is called LINQ to XML and, not so coincidentally, that is the name of the next part of this book 183 Rattz_789-3.book Page 1 84 Tuesday, October 16, 2007 2:21 PM Rattz_789-3.book Page 185 Tuesday, October 16, 2007 2:21 PM PART 3 ■■■ LINQ to XML Rattz_789-3.book... the input sequence and returning that minimum value The Third Min Prototype public static Numeric Min( this IEnumerable source, Func selector); The fourth prototype is for non-Numeric types and is like the second, except now a selector method delegate can be provided, allowing a member of each element in the input sequence to be compared while searching for the minimum value in the input... LIN Q TO XML INTRODUC TION Summary Whenever someone utters the word LINQ, the first image that most developers seem to conjure is that of performing a data query More specifically than that, they seem to want to exclude data sources other than databases LINQ to XML is here to tell you that LINQ is about XML too And not just about querying XML In this chapter, I showed you some of the pain of dealing... have a sum that included the first element twice For the second prototype’s example, shown in Listing 5- 64, I roll my own version of the Sum operator Listing 5- 64 An Example of the Second Aggregate Prototype IEnumerable intSequence = Enumerable.Range(1, 10); // I'll just output the sequence so all can see it foreach (int item in intSequence) Console.WriteLine(item); Console.WriteLine(" "); // Now... by calling the Min operator on the birth year Listing 5-55 is the code calling the Min operator Listing 5-55 An Example of the Third Min Prototype int oldestActorAge = Actor.GetActors().Min(a => a.birthYear); Console.WriteLine(oldestActorAge); And the birth year of the actor with the most plastic surgery, I mean, the earliest birth year is the following: 1960 For an example of the fourth Min prototype, . return the minimum from it. Listing 5-53. An Example of the First Min Prototype int[] myInts = new int[] { 9 74, 2, 7, 13 74, 27, 54 }; int minInt = myInts.Min(); Console.WriteLine(minInt); That. OPERATORS Listing 5-57. An Example of the First Max Prototype int[] myInts = new int[] { 9 74, 2, 7, 13 74, 27, 54 }; int maxInt = myInts.Max(); Console.WriteLine(maxInt); The results are the following: 13 74 For. source input sequence is null. Examples For an example of the first prototype, I begin with a value that I know is not in my input sequence, as shown in Listing 5 -43 Listing 5 -43 . First Contains Prototype

Ngày đăng: 06/08/2014, 08:22

TỪ KHÓA LIÊN QUAN