LINQ、Lazy 和 C#:您需要了解的有关惰性求值查询的知识
介绍
LINQ是 Language Integrated Query 的缩写,于 2007 年在 .NET Framework 3.5 版中引入。其核心概念是扩展框架(以及 C# 语言)以提供查询表达功能。我们将这些功能分为两类:查询语法和方法语法。前者更像是 SQL 查询,用于筛选出符合特定条件的不同数据,而后者则是通过类似于 SQL 查询关键字的方法调用来完成的。它允许您处理不同类型的数据,例如 SQL 数据库、XML 文档和来自 Web 服务的响应。
在本指南中,我们将看到这两种语法的示例,并讨论延迟执行和惰性求值和急切求值。
查询和方法语法
这是查询语法的一个小演示。假设我们有一个服务器及其功能的列表。
IList<string> serverList = new List<string>() {
"Parabellum - Domain Controller",
"Prostetic - DNS",
"Spooky - Domain Controller",
"Scar - DHCP" ,
"BigBoy - Web Server"
};
假设我们想查询列表中的所有域控制器。
利用查询语法方法,我们可以按如下方式实现这一点。
var DCS = from s in serverList
where s.Contains("Domain Controller")
select s;
使用方法语法,这就是解决问题的方法。
var DCS = serverList.Where(s => s.Contains("Domain Controller"));
在这两种情况下,DCS变量都保存着一个包含两个匹配服务器的列表。
延迟执行
为了深入了解 LINQ 及其其他优势,我们需要了解延迟执行。在大多数情况下,在编译期间,LINQ 表达式会在特定数据集上进行评估,并使用筛选值初始化变量。通过实现延迟执行,我们可以节省宝贵的 CPU 和 RAM 资源,因为我们不必评估特定表达式或延迟评估直到实际需要实现值。在两种情况下,这非常有用。第一种是当您的应用程序正在处理多个 GB 甚至 TB 的数据时,第二种是当您将多个查询链接在一起导致对数据集的不同操作时。
屈服
为了加深对延迟执行的理解,我们需要介绍关键字yield。此关键字是在 C# 2.0 版中引入的。它对于惰性求值至关重要,并可提高 LINQ 查询的性能。关键字yield是上下文相关的,这意味着它可以用作变量名而不会出现任何问题。让我们创建一个使用yield遍历服务器的小应用程序。
using System;
using System.Collections.Generic;
namespace Pluralsight
{
public class Server {
string _name;
string _function;
public string Name {
get { return _name; }
set { _name = value; }
}
public string Function {
get { return _function; }
set { _function = value; }
}
public Server(string Name, string Function) {
_name = Name;
_function = Function;
}
}
public class Yielder
{
public static IEnumerable<Server> ServerDB()
{
Server[] servers = new Server[]
{
new Server("Parabellum","Domain Controller"),
new Server("Pluck","DNS Server"),
new Server("Pilgrim","Web Server"),
new Server("Spark","Firewall Server"),
};
foreach(Server s in servers)
{
yield return s;
}
}
public static void Main()
{
foreach(Server s in ServerDB())
{
Console.WriteLine($"Name: {s.Name}, Function: {s.Function}");
}
Console.ReadKey();
}
}
}
这将产生以下输出。
Name: Parabellum, Function: Domain Controller
Name: Pluck, Function: DNS Server
Name: Pilgrim, Function: Web Server
Name: Spark, Function: Firewall Server
这里的关键是yield ,它允许我们迭代Server[]列表的每个元素。它不会一次返回整个列表,从而节省内存并提高性能。这也是延迟执行的一个例子,因为foreach循环逐个提取项目,并对其进行迭代。如果我们愿意,我们可以通过在yield return s;部分之后放置以下行来尝试一下。
Console.WriteLine($"Sending {s.Name}");
这将按以下方式修改输出。
Name: Parabellum, Function: Domain Controller
Sending Parabellum
Name: Pluck, Function: DNS Server
Sending Pluck
Name: Pilgrim, Function: Web Server
Sending Pilgrim
Name: Spark, Function: Firewall Server
Sending Spark
请注意, Sending...是如何出现在数组中每个元素后面的。
懒惰与渴望
使用惰性求值意味着每次调用迭代器时,仅处理源集合的单个元素。迭代器可以是自定义类或foreach或while循环,具体取决于您的上下文。
与此相反的通常是急切求值。这意味着第一次调用迭代器将返回整个集合或数据集。
结论
在本指南中,我们了解了 LINQ 如何彻底改变程序员处理不同数据集和与不同数据源交互的方式。我们看到了一些查询和方法语法的示例,并了解了惰性求值和急切求值之间的区别。希望本指南对您有所帮助,感谢您阅读本指南!
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~