C# IEnumerable,Lambda表达式和 Parallel并行编程的用法

    以前一直主要做C++和C方面的项目,对C#不太了解熟悉,但听说不难,也就一直没有在意学习C#方面的知识。今天有个C#项目,需要做些应用的扩展,同时修改一些bug。但看了C#代码,顿时觉得有些不适应了。。。其中印象很深刻的是几部分内容:IEnumerable类型和Parallel并行计算的foreach知识,我觉得C#在这个问题上做的还是很有意思的。

1. IEnumerable:

    IEnumerable<T>泛型接口支持在制定数据集合上进行迭代操作, 可以理解为一种序列或者集合,里面是某一类型的元素的集合。常用的方法如下:

成员  功能
 Aggregate  对序列应用累加器函数,可以指定累加方法
 Sum 计算序列中所有元素的和,返回值有int、long、float、double、decimal类型,并且可以指定元素到数值的映射方法
 Average 计算序列中所有元素的平均值,返回值有int、long、float、double、decimal类型,并且可以指定元素到数值的映射方法
 Max  计算序列中所有元素的最大值,返回值有int、long、float、double、decimal类型,并且可以指定元素到数值的映射方法
 Min  计算序列中所有元素的最小值,返回值有int、long、float、double、decimal类型,并且可以指定元素到数值的映射方法
 All  检查是否序列中所有元素都满足条件,可以指定条件判断方法。如果所有元素都满足条件返回True,否则返回False
 Any  检查序列中是否有任何一个元素满足条件,可以指定条件的判断方法。如果有一个以上(含一个)元素满足条件返回True,否则返回False
 Contains  检查数据系列中是否包含特定的元素,可以指定相等比较方法
 Count  返回序列中满足指定条件的元素的数量,可以指定条件判断方法
 LongCount  返回序列中满足指定条件的元素的长数量,可以指定条件判断方法
 Cast  将IEnumerable中的元素转换为指定的数据类型
 DefaultIfEmpty  返回序列中指定位置的元素。如果序列为空,则返回默认的元素值
 ElementAt  返回序列中指定索引处的元素
 ElementAtOrDefault  返回序列中指定索引处的元素。如果序列为空,则返回默认值
 First  返回序列中满足指定条件的第一个元素,可以指定条件判断方法
 FirstOrDefault  返回序列中满足指定条件的第一个元素。如果不存在则返回默认值,也可以指定条件判断方法
 Last  返回序列中满足指定条件的最后一个元素,可以指定条件判断方法
 LastOrDefault  返回序列中满足指定条件的最后一个元素。如果不存在则返回默认值,也可以指定条件判断方法
 Single  返回序列中满足指定条件的唯一元素。如果不止一个元素满足条件会引发一场,可以指定条件判断方法
 SingleOrDefault 返回序列中满足指定条件的唯一元素。如果不存在则返回默认值,如果不止一个元素满足条件会引发一场,可以指定条件判断方法 
Reverse 反转序列中元素的顺序 
 Distinct 返回序列中不重复的元素的集合,可以指定相等比较方法 
 Concat 连接两个序列,直接首尾相连。返回结果可能存在重复数据 
 Except 获取两个元素集合的差集,可以指定相等比较方法 
 Intersect  获取两个元素集合的交集,可以指定相等比较方法
 Union  获取两个元素集合的并集,可以指定相等比较方法
SequenceEqual 比较两个序列是否相等,可以指定相等比较方法 
 Where 根据制定条件对集合中元素进行筛选,返回满足条件的元素集合 
 Skip 跳过序列中指定数量的元素,然后返回剩余的元素 
 SkipWhile 跳过序列中满足指定条件的元素,然后返回剩余的元素,可以指定条件判断方法 
 Take 从序列的开头返回指定数量的连续元素 
 TakeWhile 返回从序列开始的满足指定条件的连续元素,可以指定条件判断方法 
 ToArray 从IEnumerable创建一个数组 
 ToList 从IEnumerable创建一个List 

  可以看到,提供的方法很多,也很实用,比如截断一个子序列,或者比较序列是否相等等,都是十分有用的。 而且还可以配合foreach更加简单有效的遍历集合中个各个元素。如:

// 对集合中各个元素都进行操作,后续再介绍Parallel

Parallel.ForEach(testTables, new ParallelOptions() { MaxDegreeOfParallelism = 2 }, record
=>
{
  mag.Operate(record.key1, record.Path);
});

  

2. Parallel语法

  在介绍Parallel并行计算之前,还需要先介绍一下Lambda表达式,能读懂Lambda表达式的,一般就很容易读懂Parallel并行编程的代码了。

  (以下是MSDN复制过来的说明)Lambda 表达式是一个可用于创建委托或表达式树类型的匿名函数。 通过使用 lambda 表达式,可以写入可作为参数或返回为函数调用值的本地函数。 Lambda 表达式对于编写 LINQ 查询表达式特别有用。若要创建 Lambda 表达式,必须在 Lambda 运算符 => 左侧指定输入参数(如果有),然后在另一侧输入表达式或语句块。 例如,lambda 表达式 x => x * x 指定名为 x 的参数并返回 x的平方。 您可以按照以下示例将此表达式分配给委托类型: 

  delegate int del(int i);
  static void Main(string[] args)
  {
      del myDelegate = x => x * x;
      int j = myDelegate(5); //j = 25
  }
 标准的写法: (input parameters) => expression, 如: (x, y) => x == y, 其中,左侧是输入参数,右侧相当于函数体。此表达式是返回x和y是否相等的判断表达式。

  泛型委托也可以使用Lambda表达式: 

  假设有委托: public delegate TResult Func<TArg0, TResult>(TArg0 arg0);

  可以将委托实例化为 Func<int,bool> myFunc,其中 int 是输入参数,bool 是返回值。 始终在最后一个类型参数中指定返回值。 Func<int, string, bool> 定义包含两个输入参数(int 和 string)且返回类型为 bool 的委托。 在调用下面的 Func 委托时,该委托将返回 true 或 false 以指示输入参数是否等于 5:

  Func<int, bool> myFunc = x => x == 5;
  bool result = myFunc(4); // returns false of course
  
介绍过Lambda表达式之后,就可以介绍Parallel的并行语法了。  
Parallel.ForEach标准的写法:  
Parallel.ForEach(nonGenericCollection.Cast<object>(), currentElement =>
        { 
 
           // some code here;

          });

   这个解释就是从nonGenericCollection.Cast<object>中的每一个元素,都运行后面的Lambda表达式代码,而且是多线程并行方式运行。比起以前的foreach或者for循环效率也很有了很大的提高。例子:

  IEnumerable<TRecord> testTables = warehouse.GetList();

  Parallel.ForEach(testTables, rec =>

    {

      mag.operate(rec.key1, rec.key2, rec.key3);

    }

  );

  首先定义一个IEnumerable<TRecord>的记录序列,然后后面定义一个Lambda表达式,参数是rec,函数体是大括号中的内容。也就是对于testTables里的每个元素都并行的运行函数体中的内容。如果函数体中是一个消耗时间比较长的处理事件,比如网络传输数据等内容,则并行将大大提高运行效率。

  Parallel.For标准用法:

  Parallel.For(int fromInclusive, int toExclusive, Action<int> body);

  代表从fromInclusive到toExclusive中的元素,不断的并行的执行body中的函数体。例子:

  //记录结果用
  List<string> resultData = new List<string>();

  Parallel.For(0, testData.Count() - 1, (i, loopState) =>
  {
    string data = testData[i];
    if (data.Contains("a") || data.Contains("abc"))
    {
      resultData.Add(data);
    }
  });

  这种实现方式既使运行效率得到了提高,而且不需要程序员来维护多线程编程的线程池等内容,大大减轻了多线程编程的困难,提高了编码效率。

 
 
 
 
原文地址:https://www.cnblogs.com/codefinder/p/Csharp_001.html