c#提供的ling查询极大的遍历了集合的查询过程,且使用简单方便,非常的有用,下面这篇文章主要给大家介绍了关于C#中LINQ的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
前言
本文主要的是泛谈LINQ是啥?以及常见的用法大纲如下:
- LINQ的那些根基
- LINQ的一些基本用法
LINQ的根基
IEnumerable和IEnumerator
为啥能够被foreach?
实际上,能够被foreach的对象,一定是实现了带有返回值的IEnumerator的GetEnumerator()方法的接口,而.NET内置的该接口则是IEnumerable,一般指的是IEnumerable泛型接口,让我们来看看IEnumerator接口有啥成员:
public interface IEnumerator
{
object Current
{
get;
}
bool MoveNext();
void Reset();
}
- Current:集合当前的对象
- MoveNext:是否能够移动到下一次
- Reset
因此,实际上我们进行foreach的时候,等价于:
var animals = new List<string>() { "Cat", "Dog", "Pig" };
foreach (var animla in animals)
{
Console.WriteLine(animla);
}
Console.WriteLine("-----------");
var enumerator = animals.GetEnumerator();
while (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
}
输出结果:
Cat
Dog
Pig
-----------
Cat
Dog
Pig
而能被LINQ的对象就是一个实现了IEnumerable的可被枚举的集合
LINQ的基本用法
扩展方法在LINQ的应用:LINQ的流式语法
LINQ的方法一般都是通过扩展方法了扩展的,就如最常用的几个,Where,Any,例如,我实现了一个跟Where功能类似的简化版:
public static class MyListExtension
{
public static IEnumerable<T> MyWhere<T>(this IEnumerable<T> enumable, Func<T, bool> func)
{
foreach (var item in enumable)
{
if (func(item))
{
yield return item;
}
}
}
}
其实为啥会提到用扩展方法呢?就是因为LINQ就是为了简单的能够处理复杂集合的数据,那么扩展方法就能够实现较为简单的链式查询,例如:
var result= animals.MyWhere(t => t is "Cat" or "Dog").Select(t=>t.ToUpper()).ToList();
result.ForEach(t =>Console.WriteLine(t));
输出结果:
CAT
DOG
LINQ的查询表达式:LINQ的查询语法
假如上述的例子有LINQ的查询表达式来编写,则写法是这样:
var result = (from t in animals
where t is "Cat" or "Dog"
select t.ToUpper()).ToList();
result.ForEach(t => Console.WriteLine(t));
输出结果也是一样的:
CAT
DOG
LINQ的延迟执行:IQueryable
首先我们来看看IQueryable的接口定义:
public interface IQueryable : IEnumerable
{
Type ElementType
{
get;
}
Expression Expression
{
get;
}
IQueryProvider Provider
{
get;
}
}
我们可以看到实际上IQueryable是继承了IEnumerable,因此同样具备其特性,然后主要看其三个属性:
- ElementType:集合的类型
- Expression:表达式树,这是延迟执行的重点,下面我们会一窥究竟
- IQueryProvider:IQueryable创建表达式树和执行的部分
public interface IQueryProvider
{
IQueryable CreateQuery(Expression expression);
IQueryable<TElement> CreateQuery<TElement>(Expression expression);
object? Execute(Expression expression);
TResult Execute<TResult>(Expression expression);
}
我们先来看段代码:
var result1 = (from t in animals
where (t.Equals( "Cat") || t.Equals("Dog"))
select t.ToUpper()).AsQueryable();
Console.WriteLine($"Expression:{ result1.Expression.ToString()}");
Console.WriteLine($"ExpressionType:{result1.Expression.GetType()}");
foreach (var item in result1)
{
Console.WriteLine(item);
}
Console.WriteLine("---------------");
var result2 = from t in result1
where t.Contains("CAT")
select t;
Console.WriteLine($"Expression:{ result2.Expression.ToString()}");
Console.WriteLine($"ExpressionType:{result2.Expression.GetType()}");
foreach (var item in result2)
{
Console.WriteLine(item);
}
输出如下:
Expression:System.Linq.Enumerable+WhereSelectListIterator`2[System.String,System.String]
ExpressionType:System.Linq.Expressions.ConstantExpression
CAT
DOG
---------------
Expression:System.Linq.Enumerable+WhereSelectListIterator`2[System.String,System.String].Where(t => t.Contains("CAT"))
ExpressionType:System.Linq.Expressions.MethodCallExpression2
CAT
我们从输出可以证明,实际上在返回result1和result2,就是通过IQueryProvider不断地在拼接表达式树,而最后通过foreach或者ToList等操作的时候,则才是真正调用Execute方法执行当前的IQueryable里的那个表达式树属性Expression,而像LINQ To Sql或者是EFCore等需要IQueryable这种解释型的就是去实现了IQueryProvider里面的方法
附:将内存中对象转换为 XML
LINQ 查询可以轻松地在内存中数据结构、SQL 数据库、ADO.NET 数据集和 XML 流或文档之间转换数据。 以下示例将内存中数据结构中的对象转换为 XML 元素。
class XMLTransform
{
static void Main()
{
// Create the data source by using a collection initializer.
// The Student class was defined previously in this topic.
List<Student> students = new List<Student>()
{
new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores = new List<int>{97, 92, 81, 60}},
new Student {First="Claire", Last="O'Donnell", ID=112, Scores = new List<int>{75, 84, 91, 39}},
new Student {First="Sven", Last="Mortensen", ID=113, Scores = new List<int>{88, 94, 65, 91}},
};
// Create the query.
var studentsToXML = new XElement("Root",
from student in students
let scores = string.Join(",", student.Scores)
select new XElement("student",
new XElement("First", student.First),
new XElement("Last", student.Last),
new XElement("Scores", scores)
) // end "student"
); // end "Root"
// Execute the query.
Console.WriteLine(studentsToXML);
// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
此代码生成以下 XML 输出:
<Root>
<student>
<First>Svetlana</First>
<Last>Omelchenko</Last>
<Scores>97,92,81,60</Scores>
</student>
<student>
<First>Claire</First>
<Last>O'Donnell</Last>
<Scores>75,84,91,39</Scores>
</student>
<student>
<First>Sven</First>
<Last>Mortensen</Last>
<Scores>88,94,65,91</Scores>
</student>
</Root>
参考
《C#7.0核心技术指南》
源码
BlogCodeSample/LinqSample at main · ZhengDaoWang/BlogCodeSample
总结
到此这篇关于C#中LINQ的文章就介绍到这了,更多相关C#的LINQ内容请搜索得得之家以前的文章希望大家以后多多支持得得之家!
本文标题为:带你一文了解C#中的LINQ
基础教程推荐
- C#类和结构详解 2023-05-30
- ZooKeeper的安装及部署教程 2023-01-22
- C#控制台实现飞行棋小游戏 2023-04-22
- unity实现动态排行榜 2023-04-27
- C# List实现行转列的通用方案 2022-11-02
- winform把Office转成PDF文件 2023-06-14
- C# 调用WebService的方法 2023-03-09
- C# windows语音识别与朗读实例 2023-04-27
- linux – 如何在Debian Jessie中安装dotnet core sdk 2023-09-26
- 一个读写csv文件的C#类 2022-11-06