C# 中的 System.Linq.Expressions 有何用途?
LINQ 是 .NET 4.0 中的新功能,在 .NET 3.5 等旧版本中不受支持吗?它有什么用?它似乎能够构建表达式树。实际上什么是表达式树? LINQ 是否能够从 C# 文件中提取类、方法和字段等信息?
有人可以给我提供一段工作代码来演示 LINQ 的功能吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
Linq 是在 .Net 3.5 中添加的(并添加到 c# 3.0 编译器中,并以稍微有限的形式添加到同一版本中的 VB.net 编译器
中),它是语言集成查询,尽管它涵盖了语言和语言的许多复杂添加。为了实现这一点,运行时本身很有用。
表达式功能简单地说就是程序在运行时检查传递的某些代码结构的抽象语法的能力。这些称为 lambda。从本质上讲,它们是一种更轻松地编写匿名函数的方法,同时使运行时对其结构的自省变得更容易。
与 Linq 最密切相关的“类似 SQL”功能(尽管绝不是唯一一个)被称为 Linq to Sql,其中通过如下方式:
被编译成此查询的表示形式,而不是简单地执行代码 查询。使其成为 linq to sql 的部分是“后端”,它将其转换为 sql。为此,表达式被转换为 sql server 语句,以通过从行到 .net 对象的映射以及将 c# 逻辑转换为等效的 where 子句来对链接数据库执行查询。如果 Foo 是纯 .net 对象的集合(此时它是“Linq 到对象”),则可以应用完全相同的代码,然后表达式的转换将直接转换为 .Net 代码。
上面以语言集成方式编写的 lambda 实际上相当于:
Foo.Where(f => f.Blah == "wibble).Select(f => f.Wobble);
其中 Foo 是一个类型化集合。对于数据库,类被合成来表示数据库中的值,以允许编译,并允许从 sql 区域到 .net 区域的往返值,反之亦然。
语言集成的关键方面
可以简单地选择运行它(执行 lambda 编译到的函数)或询问描述它的表达式,然后用它做一些不同的事情
。 “Linq”横幅,尽管它们并不是真正的 Linq。
例如,需要匿名类型才能轻松使用
投影
(选择可能属性的子集),但匿名类型也可以在 Linq 之外使用。Linq,特别是通过 lambda(这使得编写匿名委托在语法方面非常轻量级),导致了 c# 功能的增强。
IEnumerable
上的扩展方法(例如 Select())强化了这一点,对应于许多函数语言中的map
,而Where() 对应于filter.与匿名类型一样,它本身并不是“Linq”,尽管许多人认为它对 C# 开发有非常有益的影响(这不是一个普遍的观点,但被广泛持有)。
表达式是一个更高级的主题,使用 linq 完全不需要理解它们,尽管有一些“技巧”可以使用它们。
一般来说,只有当您尝试编写 linq 提供程序时,您才会关心表达式,该提供程序是采用表达式而不仅仅是函数的代码,并使用它来执行普通函数以外的操作,例如与外部数据源通信。
其他用途是当您希望获取一些有关函数内部正在执行的操作的元数据时,也许然后编译表达式(产生一个委托,该委托将允许您将表达式作为函数执行)并用它做一些事情,或者只是查看对象的元数据来执行反射代码,该代码在编译时验证为 此答案显示。
Linq was added in .Net 3.5 (and added to the c# 3.0 compiler as well as in slightly limited form to the VB.net compiler in the same release)
In is language integrated query, though it covers many complex additions to both the language and the runtime in order to achieve this which are useful in and of themselves.
The Expression functionality is simply put the ability for a program, at runtime, inspect the abstract syntax of certain code constructs passed around. These are called lambdas. And are, in essence a way of writing anonymous functions more easily whilst making runtime introspection of their structure easier.
The 'SQL like' functionality Linq is most closely associated with (though by no means the only one) is called Linq to Sql where by something like this:
is compiled into a representation of this query, rather than simply code to execute the query. The part that makes it linq to sql is the 'backend' which converts it into sql. For this the expression is translated into sql server statements to execute the query against a linked database with mapping from rows to .net objects and conversion of the c# logic into equivalent where clauses. You could apply exactly the same code if Foo was a collection of plain .net objects (at which point it is "Linq to objects") the conversion of the expression would then be to straight .Net code.
The lambda above written in the language integrated way is actually the equivalent of:
Foo.Where(f => f.Blah == "wibble).Select(f => f.Wobble);
Where Foo is a typed collection. For databases classes are synthesized to represent the values in the database to allow this to both compile, and to allow round tripping values from the sql areas to the .net areas and vice versa.
The critical aspect of the Language Integrated part of Linq is that the resulting language constructs are first class parts of the resulting code. Rather than simply resulting in a function they provide the way the function was constructed (as an expression) so that other aspects of the program can manipulate it.
Consumers of this functionality may simply chose to run it (execute the function which the lambda is compiled to) or to ask for the expression which describes it and then do something different with it.
Many aspects of what makes this possible are placed under the "Linq" banner despite not really being Linq themsleves.
For example anonymous types are required for easy use of
projection
(choosing a subset of the possible properties) but anonymous types can be used outside of Linq as well.Linq, especially via the lambdas (which make writing anonymous delegates very lightweight in terms of syntax) has lead to an increase in the functional capabilities of c#. this is reinforced by the extension methods on
IEnumerable<T>
like Select(), corresponding tomap
in many function languages and Where() corresponding tofilter
. Like the anonymous types this is not in and of itself "Linq" though is viewed by many as a strongly beneficial effect on c# development (this is not a universal view but is widely held).Expressions are a more advanced topic, and understanding of them is entirely unecessary to use linq, though certain 'tricks' are possible using them.
In general you would care about Expressions only if you were attempting to write linq providers which is code to take an expression rather than just a function and use that to do something other than what the plain function would do, like talk to an external data source.
Other uses would be when you wish to get some meta data about what the internals of the function is doing, perhaps then compiling the expression (resulting in a delegate which will allow you to execute the expression as a function) and doing something with it or just looking at the metadata of the objects to do reflective code which is compile time verified as this answer shows.
该问题尚未涉及的一个领域是表达式树。有一篇关于表达式树(和 lambda 表达式)的非常好的文章 这里。
关于表达式树要提到的另一件重要的事情是,通过构建表达式树来定义您将要执行的操作,您实际上不必执行任何操作。我指的是延迟执行。
One area of this question that hasn't been covered yet is expression trees. There is a really good article on expression trees (and lambda expression) available here.
The other important thing to bring up about expression trees is that by building an expression tree to define what you are going to do, you don't have to actually do anything. I am referring to deferred execution.
LINQ 是随 .NET 3.5 一起引入的。 此网站有很多示例。
LINQ was introduced with .NET 3.5. This site has a lot of examples.
System.Linq.Expressions 用于手动构建(或机器生成)表达式树。我有一种感觉,考虑到构建更复杂功能的复杂性,这个命名空间没有得到充分利用。然而它却异常强大。例如,我的一位同事最近实现了一个表达式树,它可以使用 cumultive 密度函数自动缩放任何 LINQ to SQL 对象。每列都有自己的树,编译速度很快。我一直在构建一个专门的编译器,广泛使用它们来实现基本功能并将其余生成的代码粘合在一起。
请参阅此博文了解更多信息和想法。
System.Linq.Expressions is for hand building (or machine generating) expression trees. I have a feeling that given the complexity of building more complicated functionality that this namespace is under used. However it is exceedingly powerful. For instance one of my co workers recently implemented an expression tree that can auto scale any LINQ to SQL object using a cumultive density function. Every column gets its own tree that gets compiled so its fast. I have been building a specialized compiler that uses them extensively to implement basic functionality as well as glue the rest of the generated code together.
Please see this blog post for more information and ideas.
LINQ 是一项 .NET 3.5 功能,具有内置语言支持C# 3.0 和 Visual Basic 2008。MSDN 上有大量示例 。
LINQ is a .NET 3.5 feature with built-in language support from C# 3.0 and Visual Basic 2008. There are plenty of examples on MSDN.