logo 广告
Loading...
 导航 所在位置:论坛首页 -> ┈┋电脑网络┋┈ -> Asp/Asp.Net教程 -> 使用LINQ来简化编程的7个技巧
回复
标题:使用LINQ来简化编程的7个技巧收藏 编辑 删除 楼主 | 上一篇 下一篇
ouhenliang
头像
等级:大侠
权限:普通用户
积分:99
金钱:479
声望:190
经验:190
发帖数:227
注册:2008年3月20日
资料 短消息2008-8-15 15:57:42
自从学习LINQ以来,我发现了很多使用LINQ来改善代码的方式。每一个技巧都让代码写起来更简单,可读性更强。

  这里总结了这些技巧。我会介绍如何使用LINQ来:

  ◆初始化数组

  ◆在一个循环中遍历多个数组

  ◆生成随机序列

  ◆生成字符串

  ◆转换序列或集合

  ◆把值转换为长度为1的序列

  ◆遍历序列的所有子集

  如果你在LINQ方面有心得也欢迎在评论中一起分享。

  1. 初始化数组

  通常,我们需要把数组的值初始化为相同的值或递增的序列值,或者可能是一个步进不为1的递增/递减序列。有了LINQ,我们可以在数组的初始化器中完成所有工作,不再需要循环!

  在如下的示例代码中,第一行代码初始化了一个长度为10的数组,所有元素都是-1,第二行代码初始化b为0、1、2到9,第三行代码初始化c为100、110、120到190。

  int[] a = Enumerable.Repeat(-1, 10).ToArray();

  int[] b = Enumerable.Range(0, 10).ToArray();

  int[] c = Enumerable.Range(0, 10).Select(i => 100 + 10 * i).ToArray();

  要提醒一下:如果你初始化一个很大的数组,最好不考虑这种优雅的方式而是使用传统的方式来替代。LINQ的这种解决方案会动态产生数组,因此垃圾数组需要在运行时被回收。也就是说,我总是会在小数组或测试调试代码的情况下使用这种技巧。

  2. 在一个循环中遍历多个数组

  有个朋友问我一个C#的问题:有没有办法在一个循环中遍历多个集合?他的代码差不多是这样:

  foreach (var x in array1) {

  DoSomething(x);

  }

  foreach (var x in array2) {

  DoSomething(x);

  }

  这样的话,循环主体会很大,而且他也不希望这样重复的代码。但是,他又不希望创建一个数组来保存array1和array2的所有元素。

  LINQ提供了一种优雅的解决方案:Concat操作。我们可以使用单个循环来重写上面的代码,如下:

  foreach (var x in array1.Concat(array2)) {

  DoSomething(x);

  }

  注意,由于LINQ在枚举器级别进行操作,他不会产生新的数组来保存array1和array2的元素。因此,除了优雅之外,这个方案还很高效。

  3. 生成随机序列

  这是一个生成N长度随机序列的简单技巧:

  Random rand = new Random();

  var randomSeq = Enumerable.Repeat(0, N).Select(i => rand.Next());

  有了LINQ的延迟特性,序列不会实现进行计算并保存到数组中,而是在迭代randomSeq的时候按需生成随机数。

签名

2008-8-15 15:57:42 顶部
ouhenliang
头像
等级:大侠
权限:普通用户
积分:99
金钱:479
声望:190
经验:190
发帖数:227
注册:2008年3月20日
  资料  消息 短消息编辑 删除 引用 第2楼
LINQ同样也是生成各种类型字符串的好工具。对于测试或调试,生成字符串时很有用的。假设我们需要生成一个N长度的字符串,按照“ABCABCABC”的方式。使用LINQ,解决方案非常优雅:

  string str = new string(

  Enumerable.Range(0, N)

  .Select(i => (char)(‘A’ + i % 3))

  .ToArray());

  Petar Petrov给出了另外一种有趣的方式使用LINQ来生成字符串:

  string values = string.Join(string.Empty, Enumerable.Repeat(pattern, N).ToArray());

签名
2008-8-15 15:58:07 顶部
ouhenliang
头像
等级:大侠
权限:普通用户
积分:99
金钱:479
声望:190
经验:190
发帖数:227
注册:2008年3月20日
  资料  消息 短消息编辑 删除 引用 第3楼
5. 转换序列或集合

  在C#或VB中我们不能实现把序列从T类型转换为U类型,即使T从U类继承。因此,即使把List转换为List转换为IEnumerable的话,LINQ有一个简单而有效的解决方案:

  IEnumerablestrEnumerable = …;

  IEnumerable

  如果我们需要转换List为List,LINQ也提供了解决方案,但是它会进行列表的复制:

  ListstrList = …;

  List(strList.Cast());

  Chris Cavanagh建议另外一种解决方式:

  var objList = strList.Cast().ToList();

  6. 把值转换为长度为1的序列

  当我们需要把单个值转化为一个长度为1的序列时,会怎么做?我们可以创建一个长度为1的数组,但是我还是喜欢LINQ的Repeat操作:

  IEnumerableseq = Enumerable.Repeat(myValue, 1);

  7. 遍历序列的所有子集

  有的时候,遍历数组的所有子集很有用。子集和问题、布尔可满足性问题以及背包问题都可以通过遍历某个序列的所有子集来简单解决。

  有了LINQ,我们可以如下声场所有arr数组的子集:

  T[] arr = ...;

  var subsets = from m in Enumerable.Range(0, 1 <<arr.Length)

  select

  from i in Enumerable.Range(0, arr.Length)

  where (m &(1 <<i)) != 0

  select arr[i];

  注意,如果子集的个数超过了int,上面的代码就不能工作。因此,仅当你知道arr的长度不超过30的时候才去使用这个方式。如果arr长度超过30,你应该不会是想去遍历所有的子集,因为可能这会耗费几分钟或更长的时间。

  评论和总结

  希望这些技巧对你有用,这些示例代码都使用C#实现,但是你可以很容易得改变为其它.NET语言。然而,LINQ对于支持扩展方法、lambda表达式和类型推断的语言更方便,比如C#和VB。这里的每一段代码都可行,但是我不能保证什么,请在使用前仔细检查。

  LINQ,语言级集成查询(Language INtegrated Query)

签名
2008-8-15 15:58:25 顶部
ouhenliang
头像
等级:大侠
权限:普通用户
积分:99
金钱:479
声望:190
经验:190
发帖数:227
注册:2008年3月20日
  资料  消息 短消息编辑 删除 引用 第4楼
LINQ 提供了一条更常规的途径即给 .Net Framework 添加一些可以应用于所有信息源( all sources of informa-tion )的具有多种用途( general-purpose )的语法查询特性( query facilities ),这是比向开发语言和运行时( runtime )添加一些关系数据( relational )特性或者类似 XML 特性( XML-specific )更好的方式。这些语法特性就叫做 .NET Language Integrated Query (LINQ) 。
签名
2008-8-15 15:58:48 顶部
第1页 共1页 共3个回复     <<    >>    
 快速回复
  • 支持UBB,HTML标签

  • 高级回复

  • 操作选项:评分 加精 解精 奖惩 设专题 设公告 解公告 固顶 总固顶 解固顶 结帖 解结帖 锁帖 解锁 移帖 删帖
      首页 | 购买指南 | 虚拟主机 | 特色介绍 | 下载中心 | 支付方式
    Copyright 2004-2008 BBSGood.com Powered By: BBSGood.Speed Version 5.0
      咨询电话:0575-85513832、0575-85513825(传真)、7*24小时咨询服务:13606552007 不良信息举报中心 浙ICP备05029817号
      业务QQ:38958768、客服QQ1:415896239、客服QQ2:343896043、MSN:jccsxx@hotmail.com