C#.NET的Linq查询、lambda、委托:Func<>和Action
这两天在家休息,就研究了下现在比较流行的Linq查询,以及lambda表达式和Func委托与Action委托,做了一些基础的测试,下面贴出代码,如有错误疏忽之处,请指出。
代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class LinqSelect : System.Web.UI.Page
{
public static int times = 0;
/*
*Linq查询,从一般的集合中检索一定的数据,一般可分为查询执行和立即执行,下面分别做一些解释:
*查询执行:按照相关说法,Linq查询在定义的时候并不会检索集合中的数据,即定义一个Linq查询而不去遍历这个结果集的话,Linq查询的检索操作将不会被执行;
*立即执行:即定义了Linq查询后就执行,这种定义需要将Linq查询转换为ToArray()或者ToList();
*
*官方说法:在 LINQ 中,查询的执行与查询本身截然不同;换句话说,如果只是创建查询变量,则不会检索任何数据。
*官方地址:http://msdn.microsoft.com/zh-cn/library/bb397906.aspx 官方网址对上面二者进行了较好的描述
*/
protected void Page_Load(object sender, EventArgs e)
{
//定义数据源
var numlist = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
//第一种定义方式:查询执行,定义了query对象后,实质上没有做任何的检索操作,待后面用到foreach后才执行这个query查询;
var query = from i in numlist
where i > 3 && i < 8
orderby i descending
select i;
//select query
foreach (var a in query)
{
Response.Write(a.ToString() + "<br />");
}
//第二种定义方式:立刻执行,将Linq查询强制转换为某种类型,这样赋值给变量;
var query01 = (from i in numlist
where i % 2 == 0
orderby i ascending
select i).Reverse<int>().ToArray();//经此,query01的类型为int[]
foreach (var a in query01)
{
Response.Write(a.ToString() + "<br />");
}
//第三:连接两个Linq查询的结果集,关键方法(Contact),排除数组中的元素4和5
var query02 = (from a in numlist
where a % 2 == 0 && a != 4
orderby a descending
select a).Concat(
from b in numlist
where b % 2 == 1 && b != 5
orderby b ascending
select b);
foreach (var c in query02)
{
Response.Write(c.ToString() + "<br />");
}
//第四:使用group by 子句,执行Linq查询
IList<GoodsEntity> goodsList = new List<GoodsEntity>();
for (var i = 1; i <= 20; i++)
{
goodsList.Add(new GoodsEntity(i.ToString(), "GoodsName", (i < 10 ? "001" : "002")));
}
var query03 = from goods in goodsList
where goods.ClsID.Length > 0
group goods by goods.ClsID into jh
select jh;
/*根据多个字段/条件分组
var query04 = from goods in goodsList
group goods by new { goods.GdId, goods.ClsID } into jh
select jh;
*/
/* 查询条件保存至匿名类中,
* 以下查询将结果保存至一个匿名类中,并赋予属性:clsid,g,属性可以随便加,不过要注明每个属性的类型
var query05 = from goods in goodsList
group goods by goods.ClsID into g
select new
{
clsid = g.Key,
g
};
foreach (var x in query05)
{
Response.Write(x.clsid);
foreach (GoodsEntity gd in x.g)
{
Response.Write(gd.Name + "<br />");
}
}
*/
foreach (var gd in query03)//遍历每个组信息
{
Response.Write("<br />分类" + gd.Key.ToString() + "下的商品列表:<br />");
foreach (GoodsEntity good in gd)//遍历当前组下的列表信息
{
Response.Write(good.GdId + ":" + good.Name + "<br />");
}
}
//第五:关于使用Linq查询ArrayList数据源,需要指明变量的类型
var list = new ArrayList();
for (var i = 1; i < 20; i++)
{
list.Add(new GoodsEntity(i.ToString(), "sweet", (i < 10 ? "001" : "002")));
}
var queryforArrayList = from GoodsEntity goods in list// 在from后面加上goods的类型
where int.Parse(goods.GdId) >= 5 && int.Parse(goods.GdId) <= 10
select goods;
foreach (GoodsEntity good in queryforArrayList)
{
Response.Write(string.Format("编号:{0},名称:{1}<br />", good.GdId, good.Name));
}
//第六:Linq查询的方法语法(扩展方法),直接用数据源.where/orderby ....
//数据源
string[] arr = new[] { "C#", "VB", "Flex", "JS", "Ajax" };
//IOrderedEnumerable<string> ss = arr.Where(ele => ele.Length > 2).OrderByDescending(ele => ele.Length);
string[] result = arr.Where(ele => ele.Length > 2).OrderByDescending(ele => ele.Length).ToArray<string>();//终于知道lamda表达式的好处了
string[] jieguo = arr.Where<string>(new Func<string, bool>(testss)).ToArray<string>();//这种写法与lamda写法效果相同,只是lamda更方便
Response.Write("<br />");
foreach (string s in jieguo)
{
Response.Write(s + ",");
}
//Func与Action委托
Func<int, int> fdel = getSquare;
//Func<int, int> xx = new Func<int, int>(getSquare);//此定义与以上定义方式一致
Response.Write("<br />使用Func<>泛型委托要求必须有返回值,本次返回值为:" + fdel(9).ToString() + "<br />");
Action act = new Action(HelloWorld);//无参委托
act();
Action<string> strAct = new Action<string>(WriteMsg);
strAct(null);
strAct("C#.Action");
Response.Write("<br />次数:" + times.ToString());
}
//与lamda表达式对比,原理可能是差不多的
private bool testss(string s) { times++; if (s.Length > 2) return true; else return false; }
#region Method For Delegate
private int getSquare(int x)
{
return x * x;
}
private void HelloWorld()
{
Response.Write("<br />Hello,World!<br />");
}
private void WriteMsg(string msg)
{
if (msg != null)
Response.Write("<br />本次执行的参数为:" + msg.ToString());
else
Response.Write("本次执行没有参数。");
}
#endregion
}
//分类实体类
public class ClassEntity
{
private string clid;
private string name;
/// <summary>
/// 分类编号
/// </summary>
public string ClId { set; get; }
/// <summary>
/// 分了名称
/// </summary>
public string Name { set; get; }
}
//商品类
public class GoodsEntity
{
private string gdid;
private string name;
private string clsid;
/// <summary>
/// 商品编号
/// </summary>
public string GdId { set; get; }
/// <summary>
/// 商品名称
/// </summary>
public string Name { set; get; }
/// <summary>
/// 商品分类编号
/// </summary>
public string ClsID { set; get; }
public GoodsEntity() { }
public GoodsEntity(string id, string name, string clsid)
{
this.GdId = id;
this.Name = name;
this.ClsID = clsid;
}
}
关于Func委托与Action委托,推荐学习地址:http://www.cnblogs.com/wjfluisfigo/archive/2010/04/08/1512556.html
下载测试:代码
纠正一下:原来代码里面把lambda表达式写成了lamda表达式,呵呵,感谢 Arthas-Cui 的指出,也提醒下大家,跟着感觉走的时候偶尔还是要验证一下。