LINQ查询操作中的类型关系

最近在测试中,想尝试用LINQ来简化一下测试的代码,初步学习了一下LINQ,个人感觉需要认真理解查询操作中的类型关系,在阅读MSDN文档后写下了本文,主要参考MSDN讲述理解查询操作中的类型关系,还有对C# 3.0的一个新的关键字var的理解。

首先有一段LINQ查询表达式的代码

List ret = AccountGateway.AccountLiteProvider.GetOnlineUsers(1, 10000);
var query = from onlineUser in ret
			where (onlineUser.UserId > 1301000200)
			select onlineUser.UserId;
foreach(int iUser in query)
{
	Console.WriteLine(iUser.ToString());
}


这段代码首先查询出10000个在线用户,然后在这10000个在线用户中筛选出ID大于1301000200的用户ID。其中各个变量的类型如下:

  • onlineUser — OnlineUser类
  • query — IEnumerable<int>
  • iUser — int

下面可以看一下MSDN的详细说明:

  1. 数据源的类型参数决定范围变量的类型。
  2. 选择的对象的类型决定查询变量的类型。此处的 name 为一个字符串。因此,查询变量是一个 IEnumerable<string>。
  3. foreach 语句中循环访问查询变量。因为查询变量是一个字符串序列,所以迭代变量也是一个字符串。

下面这个例子跟本文刚开始的代码例子相似

  1. 数据源的类型参数决定范围变量的类型。
  2. select 语句返回 Name 属性,而非完整的 Customer 对象。因为 Name 是一个字符串,所以 custNameQuery 的类型参数是 string,而非 Customer
  3. 因为 custNameQuery 是一个字符串序列,所以 foreach 循环的迭代变量也必须是 string

像上面这样做,有点不爽的就是每个变量类型都要编程的人来指定,C# 3.0还有一个新特性,就是隐式类型本地变量,也就是var关键字

  1. 数据源的类型参数始终为查询中的范围变量的类型。
  2. 因为 select 语句生成匿名类型,所以必须使用 var 隐式类型化查询变量。
  3. 因为查询变量的类型是隐式的,所以 foreach 循环中的迭代变量也必须是隐式的。

到此,对LINQ查询操作中的类型关系也比较明白了吧。

一个变量被var关键字声明为隐式类型本地变量后,它并不是一个动态变量,C#动态变量要等4.0的dynamic关键字。那么这个var是什么呢?其实var也是一个强类型变量,它的类型是在编译时就已经确定下来了,并不是运行时才确定下来的。例如:

var s = “I am a string”; //s的类型是string

var i = 88; //i的类型是int

s = 99; //编译出错,不能把一个int赋值给string类型变量

用Reflector看编译后的代码就是这样子:

List ret = AccountGateway.AccountLiteProvider.GetOnlineUsers(1, 10000);
IEnumerable query = from onlineUser in ret
			where onlineUser.UserId > 1301000200
			select onlineUser.UserId;
foreach (int iUser in query)
{
	Console.WriteLine(iUser.ToString());
}

稍微总结一下var

  • var还是强类型变量,不是弱类型变量
  • 使用var不会带来性能损失,因为编译为IL以后,变量的类型已经是确定,不是在运行时通过反射获取类型。

再最后,C#3.0, 3.5的很多新特性感觉都是为LINQ而出现的,例如:隐式类型化本地变量,匿名函数,匿名类,lambda表达式,扩展方法……

本文参考MSDN:http://msdn.microsoft.com/zh-cn/library/bb397924.aspx

Leave a Reply

Your email address will not be published. Required fields are marked *