LINQ查询操作中的类型关系
最近在测试中,想尝试用LINQ来简化一下测试的代码,初步学习了一下LINQ,个人感觉需要认真理解查询操作中的类型关系,在阅读MSDN文档后写下了本文,主要参考MSDN讲述理解查询操作中的类型关系,还有对C# 3.0的一个新的关键字var的理解。
首先有一段LINQ查询表达式的代码
1 2 3 4 5 6 7 8 | List<onlineUser> 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的详细说明:
- 数据源的类型参数决定范围变量的类型。
- 选择的对象的类型决定查询变量的类型。此处的 name 为一个字符串。因此,查询变量是一个 IEnumerable<string>。
- 在 foreach 语句中循环访问查询变量。因为查询变量是一个字符串序列,所以迭代变量也是一个字符串。
下面这个例子跟本文刚开始的代码例子相似
- 数据源的类型参数决定范围变量的类型。
- select 语句返回 Name 属性,而非完整的 Customer 对象。因为 Name 是一个字符串,所以 custNameQuery 的类型参数是 string,而非 Customer。
- 因为 custNameQuery 是一个字符串序列,所以 foreach 循环的迭代变量也必须是 string。
像上面这样做,有点不爽的就是每个变量类型都要编程的人来指定,C# 3.0还有一个新特性,就是隐式类型本地变量,也就是var关键字
- 数据源的类型参数始终为查询中的范围变量的类型。
- 因为 select 语句生成匿名类型,所以必须使用 var 隐式类型化查询变量。
- 因为查询变量的类型是隐式的,所以 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看编译后的代码就是这样子:
1 2 3 4 5 6 7 8 | List<onlineUser> ret = AccountGateway.AccountLiteProvider.GetOnlineUsers(1, 10000); IEnumerable<int> 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
Related posts:




Leave a Reply