标准查询运算符
特性
- 被查询的集合对象叫做序列,它必须实现IEnumerable
接口,T是类型。 - 标准查询运算符使用方法语法。
- 一些运算符返回Ienumerable对象(或其他序列),而其他的一些运算符返回标量。返回标量的运算符立即执行,并返回一个值,而不是可枚举类型对象。
其它标准查询运算符
运算符名 | 描述 |
---|---|
Where | 根据给定的谓词对序列进行过滤 |
Select | 指定要包含一个对象或对象的一部分 |
SelectMany | 一种查询类型,返回集合的集合。该方法将这些结果合并为一个单独的集合 |
Take | 接受一个输入参数count,返回序列中的前count个对象 |
Skip | 接受一个输入参数count,跳过序列中的前count个对象 |
TakeWhile | 接受一个谓词,开始迭代该序列,只要谓词对当前项的计算结果为true,就选择该项。在谓词返回第一个false的时候,该项和其余项都被丢弃 |
SkipWhile | 接受一个谓词,开始迭代该序列,只要谓词对当前项的计算结果为true,就跳过该项。在谓词返回第一个false的时候,该项和其余项都会被选择 |
Join | 对两个序列执行内联结 |
GroupJoin | 可以产生层次结果的联结,第一个序列中的各个元素都与第二个序列中的元素集合相关联 |
Concat | 连接两个序列 |
OrderBy/ThenBy | 根据一个或多个键对序列中的元素排序 |
Reverse | 反转序列中的元素 |
GroupBy | 分组序列中的元素 |
Distinct | 去除序列中的重复项 |
Union | 返回两个序列的并集 |
Intersect | 返回两个序列的交集 |
Except | 操作两个序列。返回的是第一个序列中不重复的元素减去同样位于第二个序列中的元素 |
AsEnumerable | 将序列作为IEnumerable |
ToArray | 将序列作为数组返回 |
ToList | 将序列作为List |
ToDictionary | 将序列作为Dictionary<TKey,TElement> |
ToLookup | 将序列作为LookUp<TKey,TElement> |
OfType | 所返回的序列中的元素是指定的类型 |
Cast | 将序列中所有的元素强制转换为给定的类型 |
SequenceEqual | 返回一个布尔值,指定两个序列是否相等 |
First | 返回序列中第一个与谓词匹配的元素。如果没有元素与谓词匹配,就抛出Invalid0perationException |
FirstOrDefault | 返回序列中第一个与谓词匹配的元素。如果没有给出谓词,方法返回序列的第一个元素。如果没有元素与谓词匹配,就使用该类型的默认值 |
Last | 返回序列中最后一个与谓词匹配的元素。如果没有元素与谓词匹配,就抛出Invalid0perationException |
LastOrDefault | 返回序列中最后一个与谓词匹配的元素。如果没有元素与谓词匹配,就返回默认值 |
Single | 返回序列中与谓词匹配的单个元素。如果没有元素匹配,或多于一个元素匹配,就抛出异常 |
SingleOrDefault | 返回序列中与谓词匹配的单个元素。如果没有元素匹配,或多于一个元素匹配,就返回默认值 |
ElementAt | 给定一个参数n,返回序列中第n+1个元素 |
ElementAtOrDefault | 给定一个参数n,返回序列中第n+1个元素。如果索引超出范围,就返回默认值 |
DefaultIfEmpty | 提供一个在序列为空(empty)时的默认值 |
Range | 给定一个start整型和count整型,该方法返回的序列包含count个整型,其中第一个元素的值为start,之后每个后续元素都比前一个大1 |
Repeat | 给定一个T类型的element和一个count整数,该方法返回的序列具有count个element副本 |
Empty | 返回给定类型T的空序列 |
Any | 返回一个布尔值,指明序列中是否存在满足谓词的元素 |
All | 返回一个布尔值,指明序列中的全部元素是否都满足谓词 |
Contains | 返回一个布尔值,指明序列中是否包含给定的元素 |
Count | 返回序列中元素的个数(int)。它的重载可以接受一个谓词,返回满足谓词的元素个数 |
LongCount | 返回序列中元素的个数(long)。它的重载可以接受一个谓词,返回满足谓词的元素个数 |
Sum | 返回序列中值的总和 |
Min | 返回序列中最小的值 |
Max | 返回序列中最大的值 |
Average | 返回序列中的平均值 |
Aggregate | 连续对序列中的各个元素应用给定的函数 |
查询运算符的签名
规则
- 由于运算符是泛型方法,因此每个方法名都具有相关的泛型参数(T)。
- 由于运算符是扩展IEnumerable的扩展方法,它们必须满足下面的语法条件。
- 声明为public和static。
- 在第一个参数前有this扩展指示器。
- 把IEnumerable
作为第一个参数类型。
例
public static int Count<T>(this IEnumerable<T> source);
public static T First<T>(this IEnumerable<T> source);
public static IEnumerable<T> Where<T>(this IEnumerable<T> source);
实例
两种方式调用标准查询运算符
int[] intArray = new int[] { 3, 4, 5, 6, 7, 8, 9 };
var count1 = Enumerable.Count(intArray); //方法语法
var firstNum1 = Enumerable.First(intArray);
var count2 = intArray.Count(); //扩展语法
var firstNum2 = intArray.First();
Console.WriteLine($"Count1:{count1},FirstNumer1:{firstNum1}");
Console.WriteLine($"Count2:{count2},FirstNumer2:{firstNum2}");
结果
Count1:7,FirstNumer1:3
Count2:7,FirstNumer2:3
查询表达式和标准查询运算符
标准查询运算符是进行查询的一组方法。
每一个查询表达式还可以使用带有标准查询运算符的方法语法来编写。
因此运算符可以执行任何操作
例
var numbers = new int[] { 2, 6, 4, 8, 10 };
int howMany = (from n in numbers
where n < 7
select n).Count();
Console.WriteLine($"Count:{howMany}");
结果
Count:3
委托作为参数
//Func<T, bool> predicate泛型委托
public static int Count<T>(this IEnumerable<T> source, Func<T, bool> predicate);
LINQ预定义的委托类型
LINQ定义了两套泛型委托类型与标准查询运算符一起使用,即Func委托和Action委托,各有17个成员。
例
//TR表示返回值
public delegate TR Func<out TR> ();
public delegate TR Func<in T1, out TR> (T1 a1);
public delegate TR Func<in T1, in T2, out TR> (T1 a1, T2 a2);
public delegate TR Func<in T1, in T2, in T3, out TR> (T1 a1, T2 a2, T3 a3);
使用委托示例
static bool IsOdd(int x)
{
return x % 2 == 1;
}
static void Main(string[] args)
{
int[] intArray = new int[] { 3, 4, 5, 6, 7, 8, 9 };
Func<int, bool> myDel = new Func<int, bool>(IsOdd); //委托对象
var countOdd = intArray.Count(myDel); //使用用委托
Console.WriteLine($"countOdd:{countOdd}");
Console.ReadKey();
}
结果
countOdd:4
使用Lambda表达式参数
int[] intArray = new int[] { 3, 4, 5, 6, 7, 8, 9 };
var countOdd = intArray.Count(x => x % 2 == 1);
Console.WriteLine($"countOdd:{countOdd}");
结果
countOdd:4
使用匿名方法
int[] intArray = new int[] { 3, 4, 5, 6, 7, 8, 9 };
Func<int, bool> myDel = delegate(int x)
{
return x % 2 == 1;
};
var countOdd = intArray.Count(myDel);
Console.WriteLine($"countOdd:{countOdd}");
结果
countOdd:4
使用LINQ查询XML
例1
XDocument xd = new XDocument(
new XElement("MyElements",
new XElement("first",
new XAttribute("color", "red"),
new XAttribute("size", "small")),
new XElement("second",
new XAttribute("color", "red"),
new XAttribute("size", "medium")),
new XElement("third",
new XAttribute("color", "blue"),
new XAttribute("size", "large"))));
Console.WriteLine("XML树"); //显示XML树
Console.WriteLine(xd); //显示XML树
xd.Save("SimpleSample.xml"); //保存XML树
Console.WriteLine("使用LINQ查询XML");
XDocument simpleXd = XDocument.Load("SimpleSample.xml"); //加载文档
XElement rt = xd.Element("MyElements"); //获取根节点
var xyz = from e in rt.Elements()
where e.Name.ToString().Length == 5 //查找节点中name的字符长度等于5
select e;
Console.Write("Name长度为5");
foreach (XElement x in xyz)
Console.Write($"Name:{x.Name.ToString()}");
Console.WriteLine();
foreach (XElement x in xyz) //获取特性
Console.WriteLine($"特性:Name:{x.Name},color:{x.Attribute("color").Value},size:{x.Attribute("size").Value}");
结果
XML树
<MyElements>
<first color="red" size="small" />
<second color="red" size="medium" />
<third color="blue" size="large" />
</MyElements>
使用LINQ查询XML
Name长度为5Name:firstName:third
特性:Name:first,color:red,size:small
特性:Name:third,color:blue,size:large
例2
如下代码使用了一个简单的查询来获取XML树的所有顶层元素,并且为每一个元素创建了一个匿名类型的对象。
第一个writeLine方法显示匿名类型的默认格式,
第二个writeLine语句显式格式化匿名类型对象的成员。
XDocument xd = new XDocument(
new XElement("MyElements",
new XElement("first",
new XAttribute("color", "red"),
new XAttribute("size", "small")),
new XElement("second",
new XAttribute("color", "red"),
new XAttribute("size", "medium")),
new XElement("third",
new XAttribute("color", "blue"),
new XAttribute("size", "large"))));
Console.WriteLine("XML树"); //显示XML树
Console.WriteLine(xd); //显示XML树
xd.Save("SimpleSample.xml"); //保存XML树
Console.WriteLine("使用LINQ查询XML");
XDocument simpleXd = XDocument.Load("SimpleSample.xml"); //加载文档
XElement rt = xd.Element("MyElements"); //获取根节点
var xyz = from e in rt.Elements()
select new { e.Name, color = e.Attribute("color") }; //匿名类型
foreach (var x in xyz)
Console.WriteLine(x);
foreach (var x in xyz)
Console.WriteLine($"Name:{x.Name},color:{x.Name},color.Value:{x.color.Value}");
结果
XML树
<MyElements>
<first color="red" size="small" />
<second color="red" size="medium" />
<third color="blue" size="large" />
</MyElements>
使用LINQ查询XML
{ Name = first, color = color="red" }
{ Name = second, color = color="red" }
{ Name = third, color = color="blue" }
Name:first,color:first,color.Value:red
Name:second,color:second,color.Value:red
Name:third,color:third,color.Value:blue