C#使用LINQ中Enumerable类方法的延迟与立即执行的控制

延时执行的Enumerable类方法

LINQ标准查询运算法是依靠一组扩展方法来实现的。而这些扩展方法分别在System.Linq.Enumerable和System.Linq.Queryable这连个静态类中定义。

  Enumerable的扩展方法采用线性流程,每个运算法会被线性执行。这种执行方法如果操作类似关系型数据库数据源,效率会非常低下,所以Queryable重新定义这些扩展方法,把LINQ表达式拆解为表达式树,提供程序就可以根据表达式树生成关系型数据库的查询语句,即SQL命令,然后进行相关操作。

  每个查询运算符的执行行为不同,大致分为立即执行和延时执行。延时执行的运算符将在枚举元素的时候被执行。

  Enumerable类位于程序集System.Core.dll中,System.Linq命名空间下,并且直接集成自System.Object,存在于3.5及以上的.NET框架中。Enumerable是静态类,不能实例化和被继承,其成员只有一组静态和扩展方法。

  LINQ不仅能够查询实现IEnumerable<T>或IQueryable<T>的类型,也能查询实现IEnumerable接口的类型。

理解LINQ首先必须理解扩展方法

  msdn是这样规定扩展方法的:“扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。 它们的第一个参数指定该方法作用于哪个类型,并且该参数以 this 修饰符为前缀。”

下面给个扩展方法的例子如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 扩展方法
{
  /// <summary>
  /// 为string类型定义一个扩展方法
  /// </summary>
  static class Helper
  {
    public static string MyExtenMethod(this string s)
    {
      return s.Substring(0, 2);
    }
  }
  class Program
  {
    static void Main(string[] args)
    {
      string s = "扩展方法示例";
      Console.WriteLine(s.MyExtenMethod());//调用
      Console.ReadKey(false);
    }
  }
}

程序的运行结果如下:

为了方便理解和记忆,将常用的延时执行的Enumerable类方法成员分了下组,具体如下:

1.Take用于从一个序列的开头返回指定数量的元素

2.TakeWhile 用于获取指定序列从头开始符合条件的元素,直到遇到不符合条件的元素为止

3.Skip跳过序列中指定数量的元素

4.SkipWhile 用于跳过序列总满足条件的元素,然会返回剩下的元素

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 延时执行的Enumerable类方法
{
  class Program
  {
    static void Main(string[] args)
    {
      string[] names = { "DebugLZQ","DebugMan","Sarah","Jerry","Tom","Linda","M&M","Jeffery"};
      //1.Take用于从一个序列的开头返回指定数量的元素
      //
      //a.在数组上直接使用Take方法
      foreach (string name in names.Take(3))
      {
        Console.Write("{0}  ", name);
      }
      Console.WriteLine();
      Console.WriteLine("-----");
      //b.在LINQ返回的IEnumerable<T>序列上使用Take方法
      var query = from string name in names
            where name.Length <=3
            select name;
      foreach (string name in query.Take(1))
      {
        Console.Write("{0}  ",name);
      }
      Console.WriteLine();
      Console.WriteLine("----------------------------");
      Console.ReadKey(false);
      //2.TakeWhile 用于获取指定序列从头开始符合条件的元素,直到遇到不符合条件的元素为止
      //
      var takenames = names.TakeWhile(n => n.Length>4);
      var takenames2 = names.TakeWhile((n,i)=>n.Length<10&&i<3);
      foreach (string name in takenames)
      {
        Console.Write("{0}  ", name);
      }
      Console.WriteLine();
      Console.WriteLine("-----");
      foreach (string name in takenames2)
      {
        Console.Write("{0}  ", name);
      }
      Console.WriteLine();
      Console.WriteLine("----------------------------");
      Console.ReadKey(false);
      //3.Skip跳过序列中指定数量的元素
      //
      foreach (string name in names.Skip(5))
      {
        Console.Write("{0}  ", name);
      }
      Console.WriteLine();
      Console.WriteLine("-----");
      var query_skip = (from name in names
               where name.Length >= 3
               select name).Skip(2);
      foreach (string name in query_skip.Skip(2) )
      {
        Console.Write("{0}  ", name);
      }
      Console.WriteLine();
      Console.WriteLine("----------------------------");
      Console.ReadKey(false);
      //4.SkipWhile 用于跳过序列总满足条件的元素,然会返回剩下的元素
      //跳过名字长度大于3的
      var takenames_SkipWhile = names.SkipWhile(n => n.Length >3);
      foreach (string name in takenames_SkipWhile)
      {
        Console.Write("{0}  ", name);
      }
      Console.WriteLine();
      Console.WriteLine("-----");
      var takenames_SkipWhile2 = names.SkipWhile((n,i)=>n.Length>3&&i>2);
      foreach (string name in takenames_SkipWhile2)
      {
        Console.Write("{0}  ", name);
      }
      Console.WriteLine();
      Console.WriteLine("----------------------------");
      Console.ReadKey(false);

      //小结Take、Skip获得第N到第M个元素
      var names_TakeAndSkip = names.Skip(5).Take(3);

      var names_TakeAndSkip2 = (from name in names
                   select name).Skip(5).Take(3);

      foreach (string name in names_TakeAndSkip)
      {
        Console.Write("{0}  ", name);
      }
      Console.WriteLine();
      Console.WriteLine("-----");
      foreach (string name in names_TakeAndSkip2)
      {
        Console.Write("{0}  ", name);
      }
      Console.WriteLine();
      Console.WriteLine("----------------------------");
      Console.ReadKey(false);

    }
  }
}

程序中有详细的注释不再多做说明,程序运行结果如下:

5.Reverse用于翻转序列中的元素的顺序

6.Distinct过滤掉重复的元素

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Reverse_Distinct等
{
  class Program
  {
    static void Main(string[] args)
    {
      string[] names = { "DebugLZQ", "Jerry", "Sarah", "Jerry", "Tom", "Linda", "M&M", "Jeffery" };
      //5.Reverse用于翻转序列中的元素的顺序
      string str = "反转字符串";

      var strre = str.ToCharArray().Reverse();
      var takenames = names.Reverse();

      foreach (var c in strre)
      {
        Console.Write(c);
      }
      Console.WriteLine();
      Console.WriteLine("-----");
      foreach (var c in takenames )
      {
        Console.WriteLine(c);
      }
      Console.WriteLine("----------------------------");
      Console.ReadKey(false);

      //6.Distinct 过滤掉重复的元素
      var takenames_Distinct = names.Distinct();

      foreach (var c in takenames_Distinct)
      {
        Console.WriteLine(c);
      }
      Console.WriteLine("----------------------------");
      Console.ReadKey(false);
    }
  }
}

程序的运行结果如下:

7.Union用于合并两个序列,并去掉重复项

8.Concat用于连接两个序列,不会去掉重复项

9.Intersect用于获得连个序列的交集

10.Except用于获得两个结合的差集

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Union_Concat_Intersect_Except
{
  /// <summary>
  /// DebugLZQ
  /// http://www.cnblogs.com/DebugLZQ
  /// </summary>
  class Program
  {
    static void Main(string[] args)
    {
      string[] names1 = { "DebugLZQ", "Jerry", "Sarah", "Jerry", "Tom", "Linda", "M&M", "Jeffery" };
      string[] names2 = { "DebugLZQ", "Jerry", "Sarah" };

      //7.Union用于合并两个序列,并去掉重复项
      var names_Union = names1.Union(names2);

      //8.Concat用于连接两个序列,不会去掉重复项
      var names_Concat = names1.Concat(names2);

      //9.Intersect用于获得连个序列的交集
      var names_Intersect = names1.Intersect(names2);

      //10.Except用于获得两个结合的差集
      var names_Except = names1.Except(names2);

      foreach (string name in names_Union)
      {
        Console.WriteLine(name);
      }
      Console.WriteLine("-----");
      Console.ReadKey(false);
      foreach (string name in names_Concat)
      {
        Console.WriteLine(name);
      }
      Console.WriteLine("-----");
      Console.ReadKey(false);
      foreach (string name in names_Intersect)
      {
        Console.WriteLine(name);
      }
      Console.WriteLine("-----");
      Console.ReadKey(false);
      foreach (string name in names_Except)
      {
        Console.WriteLine(name);
      }
      Console.WriteLine("-----");
      Console.ReadKey(false);
    }
  }
}

程序的运行结果如下:

11.Range 用于生成指定范围内的“整数”序列

12.Repeat用于生成指定数量的重复元素

13.Empty 用于获得一个指定类型的空序列

14.DefaultIfEmpty 用于获得序列,如果为空,则添加一个默认类型元素

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Range_Empty_DefalultIfEmpty
{
  /// <summary>
  /// DebugLZQ
  /// http://www.cnblogs.com/DebugLZQ
  /// </summary>
  class Program
  {
    static void Main(string[] args)
    {
      //11.Range 用于生成指定范围内的“整数”序列
      var num2 = Enumerable.Range(10, 15);

      //12.Repeat用于生成指定数量的重复元素
      var guest = new {Name="橙子",Age=25 };
      var Guests = Enumerable.Repeat(guest, 5);

      //13.Empty 用于获得一个指定类型的空序列
      var empty = Enumerable.Empty<string>();

      //14.DefaultIfEmpty 用于获得序列,如果为空,则添加一个默认类型元素
      //a
      var intempty = Enumerable.Empty<int>();
      Console.WriteLine(intempty.Count());
      Console.WriteLine("-----------");
      foreach (var n in intempty)
      {
        Console.WriteLine(n);
      }
      Console.WriteLine("-----------");
      Console.WriteLine(intempty.DefaultIfEmpty().Count());
      Console.WriteLine("-----------");
      foreach (var n in intempty.DefaultIfEmpty())
      {
        Console.WriteLine(n);
      }
      Console.WriteLine("--------------------------");
      Console.ReadKey(false);
      //b
      string[] names = { "DebugLZQ", "DebugMan", "Sarah", "Jerry", "Tom", "Linda", "M&M", "Jeffery" };
      var query = from name in names
            where name == "LBJ"
            select name;
      Console.WriteLine(query.Count());
      Console.WriteLine(query.DefaultIfEmpty().Count());//默认为null
      foreach (var n in query.DefaultIfEmpty())
      {
        Console.WriteLine(n);
      }
      Console.WriteLine("---------------");
      Console.ReadKey(false);
      //c指定一个默认值
      foreach (var n in intempty.DefaultIfEmpty(100))
      {
        Console.WriteLine(n);
      }
      Console.WriteLine("--------------------------");
      Console.ReadKey(false);

      foreach (var n in query.DefaultIfEmpty("James"))
      {
        Console.WriteLine(n);
      }
      Console.ReadKey(false);
    }
  }
}

程序的运行结果如下:

15.OfType筛选指定类型的元素

16.Cast类型转换

17.AsEnumerable有些数据源类型不支持Enumerable的部分查询关键字,需要转换下,譬如IQueryable

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace Cast_OfType_AsEnumerable
{
  /// <summary>
  /// DebugLZQ
  /// http://www.cnblogs.com/DebugLZQ
  /// </summary>
  class Program
  {
    static void Main(string[] args)
    {
      ArrayList names = new ArrayList();
      names.Add("DebugLZQ");
      names.Add("Jerry");
      names.Add(100);
      names.Add(new {Name="LZQ",Age=26});
      names.Add(new Stack());
      //15.OfType筛选指定类型的元素
      var takenames = names.OfType<string>();

      //16.Cast类型转换
      var takenames2 = names.OfType<string>().Cast<string>();

      //17.AsEnumerable
      var takenames3 = takenames2.AsEnumerable();

      foreach (var name in takenames3)
      {
        Console.Write("{0} ",name);
      }
      Console.ReadKey(false);

    }
  }
}

程序运行结果如下:

延时执行,顾名思义就是不是立即执行,即不是在查询语句定义的时候执行,而是在处理结果集(如遍历)的时候执行,在Enumerable类方法成员中,除了本节总结的这常用的17个外,前面博文---LINQ基本子句 中总结的8个基本子句也都是延时执行的。注意延时执行的查询程序的执行流程。

立即执行的Enumerable类方法
下面我们再来总结常用的立即执行的Enumerable类方法和它们的常用用法。同样,为了便于理解和记忆,进行一下分组:

1.ToArray序列转换成数组

2.ToList序列转换成List<T>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 立即执行的Enumerable类方法成员
{
  class Program
  {
    static void Main(string[] args)
    {
      //1.ToArray序列转换成数组
      List<string> names =new List<string> { "DebugLZQ","Sarah","Jerry","Jeffrey","M&M"};
      string[] takenames = names.ToArray();

      string[] takenames2 = (from name in names
                 where name.IndexOf("Je")>-1
                 select name).ToArray();

      //2.ToList序列转换成List<T>
      string[] namesA = { "DebugLZQ", "Sarah", "Jerry", "Jeffrey", "M&M" };
      List<string> takenames_ToList = namesA.ToList();
      List<string> takenames_ToList2 = (from name in namesA select name).ToList();

      //
    }
  }
}

程序结果显而易见,所以没有写输出语句;
3.ToDictionary把序列转换为泛型Dictionary<TKey,TValue>

4.ToLookup用于将序列转换为泛型Lookup<TKey,TValue>

Dictionary和Lookup是非常近似的一对类型,都通过“键”访问相关的元素,不同的是Dictionary的Key和Value是一一对应关系,Lookup的Key和Value是一对多关系,Lookup没有公共构造函数,时能用ToLookup构建,创建后也不能删除Lookup中的元素。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ToDictionary
{
  /// <summary>
  /// 3.ToDictionary把序列转换为泛型Dictionary<TKey,TValue>
  /// </summary>
  class Program
  {
    static void Main(string[] args)
    {
      List<GuestInfo> gList = new List<GuestInfo>()
      {
        new GuestInfo(){Name="Jeffrey", Age=33,Tel="136********"},
        new GuestInfo(){ Name="DebugLZQ", Age=25,Tel="187********"},
        new GuestInfo(){Name="Sarah", Age=24,Tel="159********"},
        new GuestInfo(){Name="Jerry", Age=33,Tel="135********"},
        new GuestInfo(){Name="Smith", Age=33,Tel="139********"}
      };
      //ToDictionary把序列转换为泛型Dictionary
      //ToDictionary重载了4个方法
      //a.用Name作为Dictionary的“键”,guest为“value”
      Dictionary<string, GuestInfo> dictionary1 = gList.ToDictionary(guest => guest.Name);
      foreach (var s in dictionary1 )
      {
        Console.WriteLine("键值{0}:{1} {2} {3}",s.Key,s.Value.Name,s.Value.Age,s.Value.Tel );
      }
      Console.WriteLine("--------------------------------");
      Console.ReadKey();
      //b.自定义比较器
      Dictionary<string,GuestInfo> dictionary2=gList.ToDictionary(guest=>guest.Name,new MyEqualityComparer<string>());
      foreach (var s in dictionary2)
      {
        Console.WriteLine("键值{0}:{1} {2} {3}", s.Key, s.Value.Name, s.Value.Age, s.Value.Tel);
      }
      Console.WriteLine("--------------------------------");
      Console.ReadKey();
      //c.用Name作为Dictionary的“键”,Tel属性为"value"
      Dictionary<string, string> dictionary3 = gList.ToDictionary(guest=>guest.Name,g=>g.Tel);
      foreach (var s in dictionary3)
      {
        Console.WriteLine("键值{0}:{1}", s.Key, s.Value);
      }
      Console.WriteLine("--------------------------------");
      Console.ReadKey();
      //d.自定义比较器
      Dictionary<string, string> dictionary4 = gList.ToDictionary(guest=>guest.Name,g=>g.Tel,new MyEqualityComparer<string>());
      foreach (var s in dictionary4)
      {
        Console.WriteLine("键值{0}:{1}", s.Key, s.Value);
      }
      Console.WriteLine("------------------------------------------------------");
      Console.ReadKey();

      ///////////////
      ///4.ToLookup用于将序列转换为泛型Lookup<TKey,TValue>。
      ///Dictionary和Lookup是非常近似的一对类型,都通过“键”访问相关的元素,不同的是Dictionary的Key和Value是一一对应关系
      ///Lookup的Key和Value是一对多关系
      ///Lookup没有公共构造函数,时能用ToLookup构建,创建后也不能删除Lookup中的元素。
      ///该方法也有4个原型,和上面的ToDictionary极像
      ///
      //a. Name的第一个字符(字符串)作key
      ILookup<string, GuestInfo> lookup1 = gList.ToLookup(guest => guest.Name.Substring(0, 1));
      foreach (var k in lookup1)
      {
        Console.WriteLine(k.Key);//键值
        foreach (var v in k)
        {
          Console.Write("{0},{1},{2}",v.Name,v.Age,v.Tel );
        }
        Console.WriteLine();
      }
      Console.WriteLine("--------------------------------");
      Console.ReadKey();
      //b自定义比较器
      ILookup<string, GuestInfo> lookup2 = gList.ToLookup(guest => guest.Name.Substring(0, 1), new MyEqualityComparer<string>());
      foreach (var k in lookup2)
      {
        Console.WriteLine(k.Key);//键值
        foreach (var v in k)
        {
          Console.Write("{0},{1},{2}", v.Name, v.Age, v.Tel);
        }
        Console.WriteLine();
      }
      Console.WriteLine("--------------------------------");
      Console.ReadKey();
      //c
      ILookup<string, string> lookup3 = gList.ToLookup(guest=>guest.Name.Substring(0,1),g=>g.Name );
      foreach (var k in lookup3)
      {
        Console.WriteLine(k.Key);//键值
        foreach (var v in k)
        {
          Console.Write("{0} ", v);
        }
        Console.WriteLine();
      }
      Console.WriteLine("--------------------------------");
      Console.ReadKey();
      //d自定义比较器
      ILookup<string, string> lookup4 = gList.ToLookup(guest=>guest.Name.Substring(0,1),g=>g.Name,new MyEqualityComparer<string>());
      foreach (var k in lookup4)
      {
        Console.WriteLine(k.Key);//键值
        foreach (var v in k)
        {
          Console.Write("{0} ", v);
        }
        Console.WriteLine();
      }
      Console.WriteLine("--------------------------------");
      Console.ReadKey();
    }
  }
}

程序运行结果如下:

没有显示完全,后面一组输出和上面最后一组相同(只是使用了自定义的比较器)。

5.SequenceEqual 比较两个序列是否相等

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SequenceEqual
{
  /// <summary>
  ///
  /// </summary>
  class Program
  {
    static void Main(string[] args)
    {
      //5.SequenceEqual 比较两个序列是否相等
      //a比较两个序列
      string[] names1 ={ "DebugLZQ","Sarah","Jerry","Jeffrey","M&M"};
      List<string> names2 = new List<string> { "DebugLZQ", "Sarah", "Jerry", "Jeffrey", "M&M" };
      bool equalornot = names1.SequenceEqual(names2);
      bool equalornot2 = names1.Skip(3).Take(2).SequenceEqual(names2.Take(3).SkipWhile(n=>n.Length==3));
      Console.WriteLine("{0},{1}",equalornot,equalornot2 );
      Console.WriteLine("----------------------------");
      Console.ReadKey();
      //b自定义比较器
      bool equalornot3 = names1.SequenceEqual(names2, new MyEqualityComparer<string>(names2.ToArray()));
      Console.WriteLine("{0}",equalornot3);
      Console.ReadKey();
    }
  }
}

自定义的比较器如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SequenceEqual
{
  //DebugLZQ提示:
  //如不知道具体的接口实现
  //可以用vs提供的自动实现接口功能实现这个接口
  class MyEqualityComparer<T> : IEqualityComparer<T>
  {
    private string[] sec;
    public MyEqualityComparer(string[] s)
    {
      sec = s;
    }
    #region IEqualityComparer<T> 成员

    public bool Equals(T x, T y)
    {
      string temp = x as string;
      if (x != null)
      {
        return sec.Contains(temp);
      }
      return false;
    }

    public int GetHashCode(T obj)
    {
      return obj.GetHashCode();
    }

    #endregion
  }
}

可以使用VS自动实现接口的智能提示,完成接口的实现。
接口的实现方式有“实现接口”和“显式实现接口”之分,上面这种实现方式即“显示接口”方式,“显示实现接口”最显著的特征是实现的接口方法加了个完全限定名,这样显式实现之后,无法通过具体的类名来访问接口方法,只能通过接口名来访问,这样可以隐藏类的复杂性。

程序运行结果如下:

6.First 返回序列第一个满足条件元素

7.FirstOrDefault 返回序列第一个满足条件元素,如果没有找到则返回默认值

8.Last

9.LastOrDefault

10.Single返回序列中唯一的元素,如果序列中包含多个元素,会引发运行错误!

11.SingleOrDefault 找出序列中满足一定条件的元素,如果序列为空则返回默认值, 如果序列中包含多个多个元素会引发运行错误!!

12.ElementAt 获得指定索引处的元素

13.ElementAtOrDefault 获得指定索引处的元素,如果超出索引,则返回元素类型的默认值

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace First_FirstOrDefault_Last_LastOrDefault_ElementAt_ElementAtOrDefaul
{
  class Program
  {
    static void Main(string[] args)
    {
      //6.First
      string[] names = { "DebugLZQ", "Sarah", "Jerry", "Jeffrey", "M&M" };
      var item = names.First();
      var item2 = names.First(n => n == "Sarah");
      Console.WriteLine("{0},{1}",item,item2 );
      Console.ReadKey();
      //7.FirstOrDefault
      var item3 = names.FirstOrDefault();
      var item4 = names.FirstOrDefault(n => n == "Sarah");
      Console.WriteLine("{0},{1}", item3, item4);
      Console.ReadKey();
      //8.Last
      var item5 = names.Last();
      var item6 = names.LastOrDefault(n => n == "Sarah");
      Console.WriteLine("{0},{1}", item5, item6);
      Console.ReadKey();
      //9LastOrDefault
      var item7 = names.LastOrDefault();
      var item8 = names.LastOrDefault(n => n == "Sarah");
      Console.WriteLine("{0},{1}", item7, item8);
      Console.ReadKey();
      //10.Single返回序列中唯一的元素,如果序列中包含多个元素,会引发运行错误!
      try
      {
        var item9 = names.Single();
      }
      catch(Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
      //
      var item10 = names.Single(n => n == "Sarah");
      Console.WriteLine("{0}",item10 );
      Console.ReadKey();
      //11.SingleOrDefault 找出序列中满足一定条件的元素,如果序列为空则返回默认值, 如果序列中包含多个多个元素会引发运行错误!!
      try
      {
        var item11 = Enumerable.Empty<string>().SingleOrDefault();
        Console.WriteLine("{0}",item11);//不报错,如果序列为空就返回默认值
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message );
      }
      try
      {
        var item12 = names.SingleOrDefault();
        Console.WriteLine("{0}", item12);//报错,序列包含多行错误
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
      var item13 = Enumerable.Empty<string>().DefaultIfEmpty("DebugLZQ").SingleOrDefault();
      Console.WriteLine("{0}", item13);
      var item14 = names.SingleOrDefault(n => n == "xxx");
      Console.WriteLine("{0}", item14);
      Console.ReadKey();
      //12ElementAt 获得指定索引处的元素
      var item15 = names.ElementAt(3);
      Console.WriteLine("{0}", item15);
      Console.ReadKey();
      //13ElementAtOrDefault 获得指定索引处的元素,如果超出索引,则返回元素类型的默认值
      var item16 = names.ElementAtOrDefault(3);
      var item17 = names.ElementAtOrDefault(100);
      Console.WriteLine("{0},{1}",item16,item17);
      Console.ReadKey();
    }
  }
}

程序运行结果如下:

14.All序列中的所有元素是否都满足条件

15.Any序列中的元素是否存在或满足条件

16.Contains确定元素是否在序列中

17.Count序列包含元素的数量

18.LongCount获取一个Int64类型的元素数量

19.Aggregate将序列元素进行累加

20.Sum序列之和

21.Average序列平均值

22.Min序列的最小值

23.Max序列的最大值

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace All_Any_Count_LongCount_Aggregate_SumAverage_Min_Max
{
  class Program
  {
    static void Main(string[] args)
    {
      string[] names = { "DebugLZQ", "Sarah", "Jerry", "Jeffrey", "M&M" };
      //14All序列中的所有元素是否都满足条件
      bool b1 = names.All(s=>s.GetTypeCode()==TypeCode.String );
      bool b2 = names.All(s=>s.IndexOf("S")>-1);
      Console.WriteLine("{0},{1}",b1,b2);
      Console.ReadKey();
      Console.WriteLine("----------------------");
      //15Any序列中的元素是否存在或满足条件
      bool p1 = names.Any();
      bool p2 = names.Any(s => s.IndexOf("S")>-1);
      Console.WriteLine("{0},{1}", p1, p2);
      Console.ReadKey();
      Console.WriteLine("----------------------");
      //16Contains确定元素是否在序列中
      //a
      bool q1 = names.Contains("MM");
      //b自定义比较函数
      bool q2 = names.Contains("MM", new MyEqualityComparer<string>());
      Console.WriteLine("{0},{1}", q1, q2);
      Console.ReadKey();
      Console.WriteLine("----------------------");
      //17Count序列包含元素的数量
      int i1 = names.Count();
      int i2 = names.Count(n => n.Length == 5);
      Console.WriteLine("{0},{1}", i1, i2);
      Console.ReadKey();
      Console.WriteLine("----------------------");
      //18LongCount获取一个Int64类型的元素数量
      long j1 = names.LongCount();
      long j2 = names.LongCount(n => n.Length == 5);
      Console.WriteLine("{0},{1}",j1, j2);
      Console.ReadKey();
      Console.WriteLine("----------------------");
      //19Aggregate将序列元素进行累加
      int[] nums = { 10,20,30,40,50};
      int a1 = nums.Aggregate((n1,n2)=>n1+n2);//150
      int a2 = nums.Aggregate(50,(n1,n2)=>n1+n2);//200
      Console.WriteLine("{0},{1}", a1, a2);
      string s1 = names.Aggregate((name1,name2)=>string.Format("{0}、{1}",name1,name2));
      string s2= names.Aggregate("The result is ",(name1, name2) => string.Format("{0}、{1}", name1, name2));
      Console.WriteLine("{0}", s1);
      Console.WriteLine("{0}", s2);
      Console.ReadKey();
      Console.WriteLine("----------------------");
      //20Sum序列之和
      int sum = nums.Sum();
      //21Average序列平均值
      double avg = nums.Average();
      //22Min序列的最小值
      int min = nums.Min();
      //23Max序列的最大值
      int max=nums.Max();
      Console.WriteLine("{0},{1},{2},{3}", sum, avg,min,max);
      Console.ReadKey();

    }
  }
}

程序运行结果如下:

(0)

相关推荐

  • C#使用Process类调用外部exe程序

    在编写程序时经常会使用到调用可执行程序的情况,本文将简单介绍C#调用exe的方法.在C#中,通过Process类来进行进程操作. Process类在System.Diagnostics包中. 示例一 复制代码 代码如下: using System.Diagnostics; Process p = Process.Start("notepad.exe"); p.WaitForExit();//关键,等待外部程序退出后才能往下执行 通过上述代码可以调用记事本程序,注意如果不是调用系统程序,

  • C#实现动态生成静态页面的类详解

    本文实例讲述了C#实现动态生成静态页面的类.分享给大家供大家参考,具体如下: 动态生成静态页面有许多好处,比如生成html网页有利于被搜索引擎收录.同时,由于减少了数据访问,减轻对数据库访问的压力,提高了网页打开速度. 基本思路: 使用一个字符串作为页面模板,再页面中包含用若干标志(用 {标志名} 表示),生成页面时,将标志替换为对应的值. 实现方法: 在初始化TextTemplate实例时读入模板,以标志为分割点将模板分割成几部分,生成页面时只需简单的将模板内容和标志的值连接起来.例如: 假如

  • C#中的委托数据类型简介

    什么是委托? 委托是一个类型安全的对象,它指向程序中另一个以后会被调用的方法(或多个方法).通俗的说,委托是一个可以引用方法的对象,当创建一个委托,也就创建一个引用方法的对象,进而就可以调用那个方法,即委托可以调用它所指的方法. 来看下面的例子,类deleMthod定义了3个方法,add.minus和multi,他们都具有相同的输入参数列表(int x,int y)和输出参数类型int,那么我们就说这三个方法具有相同的方法签名.开发者可以抽象地用 int 某名称(int x,int y) 的一种

  • ASP.NET在底层类库中获取Session C#类中获取Session 原创

    类库中获取Session首先要添加引用 获取Session 复制代码 代码如下: string user = (string)HttpContext.Current.Session["user"]; 获取Page 复制代码 代码如下: System.Web.UI.Page page = (System.Web.UI.Page)HttpContext.Current.Handler; 获取当前 Request Response 等对象都是在这里 复制代码 代码如下: HttpRespon

  • C#中的静态成员、静态方法、静态类介绍

    1.静态成员.实例成员 1.1定义及说明 数据成员: 静态成员:静态成员变量是和类相关联的,可以作为类中"共"有的变量(是一个共性的表现),他不依赖特定对象的存在,访问的时候通过类名加点操作符加变量名来访问. 实例成员:实例成员变量是和对象相关联的,访问实例成员变量依赖于实例的存在. 函数成员: 静态方法:静态方法是不属于特定对象的方法,静态方法可以访问静态成员变量和静态方法:静态方法不可以直接访问实例变量和实例方法,可以间接调用,首先要创建一个类的实例,然后通过这一特定对象来调用静态

  • C#编程中枚举类型的使用教程

    枚举类型(也称为枚举)为定义一组可以赋给变量的命名整数常量提供了一种有效的方法.例如,假设您必须定义一个变量,该变量的值表示一周中的一天.该变量只能存储七个有意义的值.若要定义这些值,可以使用枚举类型.枚举类型是使用 enum关键字声明的. enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }; enum Months : byte { Jan, Feb, Mar, Apr, May, Jun,

  • 结合.net框架在C#派生类中触发基类事件及实现接口事件

    在派生类中引发基类事件 以下简单示例演示了在基类中声明可从派生类引发的事件的标准方法.此模式广泛应用于 .NET Framework 类库中的 Windows 窗体类. 在创建可用作其他类的基类的类时,应考虑如下事实:事件是特殊类型的委托,只可以从声明它们的类中调用.派生类无法直接调用基类中声明的事件.尽管有时需要事件仅由基类引发,但在大多数情形下,应该允许派生类调用基类事件.为此,您可以在包含该事件的基类中创建一个受保护的调用方法.通过调用或重写此调用方法,派生类便可以间接调用该事件. 注意:

  • C#简单邮件群发通用类

    本文实例为大家介绍了C#邮件群发通用类,供大家参考,具体内容如下 public static class Email { /// <summary> /// 发件人 /// </summary> public static string mailFrom { get; set; } /// <summary> /// 收件人 /// </summary> public static string[] mailToArray { get; set; } ///

  • C#中使用XmlDocument类来创建和修改XML格式的数据文件

    通过XmlDocument类修改XML文档数据,通常需要以下几个主要步骤或其中几个步骤. (1)获取一个包含XML文档数据的XmlDocument类对象,通常有两种方法来实现这个功能: 通过XmlDocument类的构造函数创建不包含任何结点的空对象,常用默认构造函数. (2)通过XmlDocument类的ChildNodes和Item属性获取某个结点(XmlNode类型),通过XmlNode的Name.Value.InnerText等属性修改选中结点的数据. (3)通过XmlDocument类

  • 分享C#中几个可用的类

    本文实例为大家介绍了几个可用的类,供大家参考,具体内容如下 1.SQLHelper类 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.SqlClient; using System.Data; using System.Configuration; namespace MySchool.DAL { public static class

随机推荐