LINQ和Rx简单介绍

相信大家都用过Language Integrated Query (LINQ),他是一种强大的工具能够从集合中提取数据。Reactive Extensions(Rx)是对LINQ的一种扩展,他的目标是对异步的集合进行操作,也就是说,集合中的元素是异步填充的,比如说从webservice或者云端获取数据然后对集合进行填充。

LINQ是从C#3.0开始引入的语言特性,而Rx起源于Microsoft DevLabs小组的研究,他扩展了LINQ的一些特性,目前Rx支持多种平台如JavaScript,Windows Phone。随着数据处理变得复杂,LINQ使得我们的处理逻辑变得简单清晰,同样地,随着越来越多的数据通过从云端异步获取,Rx使得这种异步数据处理操作变得简单和容易维护。

本文简要介绍LINQ和Rx的重要性,并用代码展示了LINQ和Rx的一些基本操作。

1. 什么是LINQ和Rx

1.1 什么是LINQ

LINQ是.NET的一个扩展,专门用来对数据集合,关系数据,XML文件等对象进行查询和提取数据的技术,他提供了统一的类似SQL的语法来对数据进行查询,而不用关心数据源的不同。

LINQ使得我们的代码风格更加声明化和函数化,在我之前的一篇文章 查询表达式和循环控制读者可以明显的感受到这一点。声明式编程风格相信大家都使用过,比如说C#中的特性(AttributeClass),WPF中的XAML以及F#语言,大家可以从中体会到,声明式编程风格强调的是实现的逻辑和需求,而不是具体的执行步骤。LINQ和Rx是C#中声明式和函数式编码风格的一部分,他强调如何能够完成想要的功能,而不是专注于怎么样去实现。函数式编程(Function Programming)和传统的命令式编程(Imperative Programing)风格相比,代码更加简洁明了,容易维护。

命令是编程中,程序通常有几个步骤组成,在某一步骤中通常有循环,循环体内是具体的逻辑。在声明式编程中,使用更高一层的抽象来表达意图。举例来说,命令式编程式编程通常是这样的“打开所有员工集合,遍历集合中的元素,看该员工是否是经理,如果是,则将工资增加20%,然后将增加后的工资更新回集合中去”,而声明式编程风格大体会是“将经理的工资增加20%”,可见,命令式编程注重的是如何完成某一任务,生命式编程则注重的是要完成什么任务。

1.2 什么是Rx

Rx提供了一种新的组织和协调异步事件的方式,例如协调多个从云端返回的多个异步的数据流。Rx能够是的我们用一个简单的方式来处理这些数据流,极大的简化了代码的编写。例如,.NET中传统的Begin/End异步编程模式在处理单个异步操作时可以应付,但是如果同时多个异步调用时,线程控制就会使得代码变得比较复杂。使用Rx,Begin/End模式就变成了一条简单的方法,这使得代码更加清晰和容易理解。

Rx最显著的特性是使用可观察集合(Observable Collection)来达到集成异步(composing asynchronous)和基于事件(event-based)的编程的效果。Rx有一些几个特性。

  • 组合(Composing): Reactive Extension的首要目标之一就是将多种异步操作组合起来是的代码更加简单。要做到这一点,数据流必须定义清楚,这样代码就很清晰集中,使得异步操作代码异步处理代码不会充斥整个应用程序。
  • 异步(Asynchronous): 虽然Rx不仅仅能处理异步操作,但是使用Rx,大大简化了异步操作的实现,并且代码容易理解进而容易维护。
  • 基于事件(Event-based): Rx简化了传统的异步编程方式,在后面的文章中我们会看到拖放(drag and drop)模式的实现
  • 可观察集合(Observable collections): Obervable Collection是Rx的核心,它是一种集合,集合的元素在第一次访问的时候肯能还没有填充。它对与Rx的重要性类始于enumerable集合对LINQ的重要性。

2. 获取和安装Rx

如果使用.NET 3或者之后的版本,那么LINQ已经集成到framework中了,同样,如果安装了Windows Phone开发工具,Rx的WindowsPhone版本也会自动安装。要获得最新的Rx可以访问其官网(http://msdn.microsoft.com/en-us/data/gg577609)。

3. Rx与LINQ的异同

在处理静态集合数据方面,LINQ使用类似SQL的语法来操作和使用不同来源的数据。相反,Rx被设计出来用来处理将来才会填充好的集合,也就是说,集合类型定义好了,但是集合中的元素可能在未来的某一时刻才会被填充。

在使用LINQ之前要求集合中的所有元素都可以使用,也就是说在使用LINQ集合进行操作时,需要一个初始的静态的集合。但是,问题来了,如果集合中有些数据目前还在处理之中,或者说是调用远处的webservice结果还没有返回,或者是一些实时产生的数据会不断的往集合中添加,那么对于这类集合LINQ不知道该怎么处理,因为他们不是静态的,集合中的元素会在未来的某一个时刻继续添加,并且数据到达的事件不确定。Rx就是针对这种数据集合设置的,它是的操作这类数据集合就像LINQ操作静态数据集合那样简单。

就像大家开始接触LINQ那样会感觉不容易理解,初次接触Rx也会有类似的问题。一旦理解和熟悉了Rx的语法,就会感觉和LINQ一样亲切,一些复杂的异步操作使用Rx可以非常简单的实现。

LINQ和Rx在技术上有很多相似的地方。在LINQ对集合进行一系列操作如添加,移除,修改,提取后,会得到一个新的集合,新集合只是原始集合的一个修改版本。Rx也是一样,咋一看,集合和数据流看起来非常不同,但是他们在很多关键的地方有联系,这就是我们将数据流称之为未来的集合的原因。集合和数据流都是多数据按某种顺序进行排列。LINQ和Rx可以这些序列进行一系列操作然后得到一个新的序列。

使用LINQ和Rx能够带给我们很多好处,他们有一下好处:

  • 他们是.NET框架中的一级成员(first-class member)。Visual Studio中完全支持对LINQ和Rx的智能感知和语法高亮。
  • 他们能够以一种统一的方式来处理各种数据源产生的数据,这些数据源包括数据库或者XML文件。
  • 他们具有很强的扩展性。你可以编写自己的类库来扩展这些框架。
  • 组合性。LINQ和Rx都可以将一系列复杂的操作和变化组合到一小片代码段中。使得代码更加简洁。
  • 声明式风格。LINQ和Rx为编程带来了一些函数式编程的风格。
  • 简化实现。很多时候一条或者几条LINQ,Rx语句就能轻易实现很多需要复杂和晦涩的语句才能完成的功能。

4. Rx和LINQ的简单例子

讲了这么多,下面来看看一个简单的例子来说明LINQ和Rx的用法。大家可能对LINQ比较熟悉,那么先看看LINQ。

static void Main(string[] args)
{
List<Int32> its = Enumerable.Range(1, 15).ToList();
its.Where(i => i % 2 == 0).ToList().ForEach(i => Console.Write("{0} ", i));
Console.ReadKey();
}

上述代码输出结果:2 4 6 8 10 12 14

上面例子很简单,首先使用Enumerable对象的Range方法初始化一个list集合,然后使用LINQ的方法型表达式过滤所有偶数,LINQ语句代码执行返回一个IEnumerable集合,然后使用IEnumerable集合的扩展方法Tolist将其转换为List集合,在调用ForEach方法传入一个匿名方法将所有集合中的所有元素打印出来,整个代码紧凑易读,逻辑清晰。

下面来如何使用Rx实现上述功能。要使用Rx必须添加System.Reactive.dll,默认安装路径下,我本机的地址为C:\Program Files\Microsoft Reactive Extensions SDK\v1.0.10621\Binaries\.NETFramework\v4.0\ System.Reactive.dll。

static void Main(string[] args)
{
IObservable<Int32> input = Observable.Range(1, 15);
input.Where(i => i % 2 == 0).Subscribe(x => Console.Write("{0} ", x));
Console.ReadKey();
}

代码输出结果和LINQ版本的完全相同,但是程序的内在逻辑完全不同。上述代码中,首先使用Observable对象产生一个IObservable对象集合,然后使用Where子句过滤其中的元素,得到一个新的IObservable对象,然后对对象中的每一个元素注册一个方法,上述代码中使用的是匿名方法将每个元素打印出来。当集合中有元素时,因为元素注册了该方法,所以就会调用该方法把元素打印出来。

LINQ和Rx的能处理的集合类型不同导致其产生内在逻辑不同,下面先简单了解一下Enumerable集合和Observable集合。

5. Enumerable集合和Observable集合

LINQ和Rx都是用来对集合进行操作。LINQ操作的集合实现了IEnumerable借口,能够使用foreach语句遍历集合。而Rx操作的集合实现了IEnumerable,IQueryable集合,这样的集合称之为Observable集合。大家对Enumerable集合可能很熟悉,他是foreach语句的基础,我的另一篇文章对这个有详细介绍,这里就不多说了,下面主要来看看Observable集合。

Rx对Observable集合进行操作,这个集合的命名是从观察者设计模式得来的,观察者模式的基础是委托和事件,所以要了解这一模式需要理解委托和事件,在这里推荐张子阳的文章C#中的委托和事件。Enumebrable集合中所有的元素在集合中都已经填充好了,是静态的,用户可以使用“拉”的方式从集合中遍历元素进行处理。而Observable集合则不同,在创建该集合时,集合中的元素可能会在以后的某个时间才能添加进去。由于集合注册了事件,一旦集合中的元素到达,就会触发这一事件,将信息“推”到注册者哪里去。

现在在Windows Phone中演示如何使用这两个集合,在WindowPhone界面上添加两个ListBox控件,一个使用Enumerable集合填充一个使用Observable集合填充。具体步骤如下:

1. 新建一个Windows Phone项目,在界面上放两个ListBox,分别命名为lblEnumerable和lblObservable。

2. 添加System.Observable.dll和Microsoft.Phone.Reactive.dll,并在代码中添加对Microsoft.Phone.Reactive的引用。

3. 初始化一个数组变量,然后分别利用两种方式分别对这两个ListBox进行填充。

完整代码如下:

using Microsoft.Phone.Controls;
using Microsoft.Phone.Reactive; namespace IntroductionRxPhoneApp
{
public partial class MainPage : PhoneApplicationPage
{
readonly List<String> fruits = new List<string>{
"Apple","Orange","Banana","Pears","melon"};
// 构造函数
public MainPage()
{
InitializeComponent();
PopulateCollection();
} private void PopulateCollection()
{
//使用Enumerable集合进行填充
fruits.ForEach(fruit => lblEnumerable.Items.Add(fruit)); //使用Observable集合进行填充
IObservable<String> observable = fruits.ToObservable();
observable.Subscribe(fruit => lblObservable.Items.Add(fruit));
}
}
}

运行程序可以看到两个下拉框中的内容是一样的。

6. 结语

本文简要介绍了什么是Rx以及Rx如何对LINQ进行的扩展。并以实际代码简单演示了Rx的用法,希望本文对您了解Rx有所帮助,因为Rx和LINQ有在技术方面有很多共同的地方,所以下一篇文章将会介绍LINQ的一些核心的用法,敬请期待!

Reactive ExtensionsLINQ和Rx简单介绍的更多相关文章

  1. Reactive Extensions(Rx)并发浅析

    Reactive Extensions(Rx)并发浅析 iSun Design & Code .Net并行编程 - Reactive Extensions(Rx)并发浅析 关于Reactive ...

  2. .Net并行编程 - Reactive Extensions(Rx)并发浅析

    关于Reactive Extensions(Rx) 关于Reactive Extensions(Rx),先来看一下来自微软的官方描述: The Reactive Extensions (Rx) is ...

  3. 牛刀小试:使用Reactive Extensions(Rx),对短时间内多次发生的事件限流

    我之前有一篇文章介绍到了Reactive Extension这个组件,请参考下面的文章,其中有一些基本的概念和相关的链接 牛刀小试:使用Reactive Extensions(Rx),一行代码实现多线 ...

  4. 使用Reactive Extensions(Rx),对短时间内多次发生的事件限流

    使用Reactive Extensions(Rx),对短时间内多次发生的事件限流 牛刀小试:使用Reactive Extensions(Rx),对短时间内多次发生的事件限流 我之前有一篇文章介绍到了R ...

  5. 第一篇:SpringBoot2.0简单介绍

    距离Spring Boot1.0发布已经4年了,今年3月份SpringBoot2.0正式发布.让我们一起来了解一下它. Spring Boot主要依赖于Spring,整合了很多框架的使用方式,帮助开发 ...

  6. [原创]关于mybatis中一级缓存和二级缓存的简单介绍

    关于mybatis中一级缓存和二级缓存的简单介绍 mybatis的一级缓存: MyBatis会在表示会话的SqlSession对象中建立一个简单的缓存,将每次查询到的结果结果缓存起来,当下次查询的时候 ...

  7. 利用Python进行数据分析(7) pandas基础: Series和DataFrame的简单介绍

    一.pandas 是什么 pandas 是基于 NumPy 的一个 Python 数据分析包,主要目的是为了数据分析.它提供了大量高级的数据结构和对数据处理的方法. pandas 有两个主要的数据结构 ...

  8. 利用Python进行数据分析(4) NumPy基础: ndarray简单介绍

    一.NumPy 是什么 NumPy 是 Python 科学计算的基础包,它专为进行严格的数字处理而产生.在之前的随笔里已有更加详细的介绍,这里不再赘述. 利用 Python 进行数据分析(一)简单介绍 ...

  9. yii2的权限管理系统RBAC简单介绍

    这里有几个概念 权限: 指用户是否可以执行哪些操作,如:编辑.发布.查看回帖 角色 比如:VIP用户组, 高级会员组,中级会员组,初级会员组 VIP用户组:发帖.回帖.删帖.浏览权限 高级会员组:发帖 ...

随机推荐

  1. xml(3)--dom4j实现crud操作

    1.XML解析技术概述 (1)XML解析方式分为两种:dom和sax     dom:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种标准方 ...

  2. C#之网络

    首先很不好意思,前段时间把评论的功能给关掉啦,BUT NOW 此功能以开放,欢迎小伙伴们拍砖. 1网络 在网络环境下,我们最感兴趣的两个名称空间是System.Net和System.Net.Socke ...

  3. Learning Cocos2d-x for WP8(5)——详解Menu菜单

    原文:Learning Cocos2d-x for WP8(5)--详解Menu菜单 C#(wp7)兄弟篇Learning Cocos2d-x for XNA(5)——详解Menu菜单 菜单是游戏必不 ...

  4. VS2010,原来还有这些快捷键,果断记下来!

    一直认为VS的快捷键跟eclipse比起来差远了,那些由于不知道还有如此多有效却不知的快捷键阿 1. 检查括号匹配(在左右括号间切换): Ctrl +] 2. 选中从光标起到行首(尾)间的代码: Sh ...

  5. 大话设计模式C++达到-文章12章-外观模式

    一.UML画画 关键词:添加Facade层. 二.概念 外观模式:为子系统中的一组接口提供一个一致的界面.此模式定义了一个高层接口,这个接口使得这一子系统更加easy使用. 三.说明 Q:外观模式在什 ...

  6. Xamarin For Visual Studio 3.7.165 完整离线破解版

    原文 Xamarin For Visual Studio 3.7.165 完整离线破解版 Xamarin For Visual Studio就是原本的Xamarin For Android 以及 Xa ...

  7. Percona Data Recovery Tool for InnoDB工具恢复单表的案例

    今天上班有个朋友询问我,相关Percona Data Recovery Tool for InnoDB恢复数据中的一些问题,比如说delete,没法恢复数据,原先做过类似的异常处理就,再次模拟了下相关 ...

  8. ufldl学习笔记和编程作业:Softmax Regression(softmax回报)

    ufldl学习笔记与编程作业:Softmax Regression(softmax回归) ufldl出了新教程.感觉比之前的好,从基础讲起.系统清晰,又有编程实践. 在deep learning高质量 ...

  9. 无法识别的属性“targetFramework”。请注意,属性名是大写和小写。错误的解决方案

    "/CRM"应用server错. 配置错误 说明: 在处理向该请求提供服务所需的配置文件时出错.请检查以下的特定错误具体信息并适当地改动配置文件. 分析器错误消息: 无法识别的属性 ...

  10. WCF-001:WCF的发布

    随着“云”时代的到来,“云”已经无处不在了.什么是“云”,无非就是利用互联网强大的功能建立多个服务器,然后再利用互联网的传输数据的特点将数据从某个服务器中读取出来或者将你的数据上传上去.当然这个服务器 ...