public static void LinqDemo01() { string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; var shortDigits = digits.Where((dd, aa) => dd.Length < aa); Console.WriteLine("Short digits:"); foreach (var d in shortDigits) Console.WriteLine("The Word {0} is shorter than its value.", d); }
输出结果:
Short digits: The word five is shorter than its value. The word six is shorter than its value. The word seven is shorter than its value. The word eight is shorter than its value. The word nine is shorter than its value.
下面我们就来分析上述代码中最核心的代码:
digits.Where((dd, aa) => dd.Length < aa);
这行代码都赶了些什么?
1、Where子句其实是用扩展方法来实现的
如果你对扩展方法不熟悉,请先看我之前的几篇博客:
C#3.0 中的扩展方法 (Extension Methods)
C#3.0 中使用扩展方法来扩展接口
Orcas Beta1 对多个同名扩展方法的处理逻辑
微软替我们实现的 Where 子句对应的扩展函数实际是如下的定义:
namespace System.Linq { public delegate TResult Func(TArg0 arg0, TArg1 arg1); public static class Enumerable { public static IEnumerable Where(this IEnumerable source, Func predicate); public static IEnumerable Where(this IEnumerable source, Func predicate); } }
public static IEnumerable Select(this IEnumerable source, Func selector);
public delegate TResult Func(TArg0 arg0, TArg1 arg1);
SelectMany 子句使用数组索引的例子
几个句子组成的数组,我们希望把这几个句子拆分成单词,并显示每个单词在那个句子中。查询语句如下:
public static void Demo01() { string[] text = { "Albert was here", "Burke slept late", "Connor is happy" }; var tt = text.SelectMany((s, index) => from ss in s.Split(' ') select new { Word = ss, Index = index }); foreach (var n in tt) Console.WriteLine("{0}:{1}", n.Word,n.Index); }
public static void Linq27() { int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; var laterNumbers = numbers.SkipWhile((n, index) => n >= index); Console.WriteLine("All elements starting from first element less than its position:"); foreach (var n in laterNumbers) Console.WriteLine(n); }
输出结果:
All elements starting from first element less than its position: 1 3 9 8 6 7 2 0
First 、FirstOrDefault、Any、All、Count 子句
注意:
101 LINQ Samples 中 First - Indexed、FirstOrDefault - Indexed、 Any - Indexed、All - Indexed、Count - Indexed 这五个例子在 Orcas Beta1中已经不在可用,即下面代码是错误的。
public void Linq60() { int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; int evenNum = numbers.First((num, index) => (num % 2 == 0) && (index % 2 == 0)); Console.WriteLine("{0} is an even number at an even position within the list.", evenNum); }
public void Linq63() { double?[] doubles = { 1.7, 2.3, 4.1, 1.9, 2.9 }; double? num = doubles.FirstOrDefault((n, index) => (n >= index - 0.5 && n <= index + 0.5)); if (num != null) Console.WriteLine("The value {1} is within 0.5 of its index position.", num); else Console.WriteLine("There is no number within 0.5 of its index position.", num); }
public void Linq68() { int[] numbers = { -9, -4, -8, -3, -5, -2, -1, -6, -7 }; bool negativeMatch = numbers.Any((n, index) => n == -index); Console.WriteLine("There is a number that is the negative of its index: {0}", negativeMatch); }
public void Linq71() { int[] lowNumbers = { 1, 11, 3, 19, 41, 65, 19 }; int[] highNumbers = { 7, 19, 42, 22, 45, 79, 24 }; bool allLower = lowNumbers.All((num, index) => num < highNumbers[index]); Console.WriteLine("Each number in the first list is lower than its counterpart in the second list: {0}", allLower); }
public void Linq75() { int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; int oddEvenMatches = numbers.Count((n, index) => n % 2 == index % 2); Console.WriteLine("There are {0} numbers in the list whose odd/even status " + "matches that of their position.", oddEvenMatches); }
要实现这个功能,可以用Where 子句,如下:
public static void Linq60() { int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; int evenNum = numbers.Where((num,index) =>( num % 2 == 0 && index %2 == 0) ).First(); Console.WriteLine("{0} is an even number at an even position within the list.", evenNum); }
public static void Linq63() { double?[] doubles = { 1.7, 2.3, 4.1, 1.9, 2.9 }; double? num = doubles.Where((n, index) => (n >= index - 0.5 && n <= index + 0.5)).FirstOrDefault(); if (num != null) Console.WriteLine("The value {1} is within 0.5 of its index position.", num); else Console.WriteLine("There is no number within 0.5 of its index position.", num); }
public static void Linq68() { int[] numbers = { -9, -4, -8, -3, -5, -2, -1, -6, -7 }; bool negativeMatch = numbers.Where((n, index) => n == -index).Any(); Console.WriteLine("There is a number that is the negative of its index: {0}", negativeMatch); }
public static void Linq71() { int[] lowNumbers = { 1, 11, 3, 19, 41, 65, 19 }; int[] highNumbers = { 7, 19, 42, 22, 45, 79, 24 }; bool allLower = lowNumbers.Where((num, index) => num < highNumbers[index]).All(n => true); Console.WriteLine("Each number in the first list is lower than its counterpart in the second list: {0}", allLower); }
public static void Linq75() { int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; int oddEvenMatches = numbers.Where((n, index) => n % 2 == index % 2).Count(); Console.WriteLine("There are {0} numbers in the list whose odd/even status " + "matches that of their position.", oddEvenMatches); }