目录
写在前面
上篇文章是本系列的小插曲,也是在项目中遇到,觉得有必要总结一下,就顺手写在了博客中,也希望能帮到一些朋友。本文将继续介绍linq系列的基础知识,隐式类型,自动属性,初始化器,匿名类的相关概念,这些内容也许与linq相关也许不相关,但还是放一起总结吧,也算是复习了。部分内容通过反编译的方式一探究竟。
系列文章
隐式类型
先看看Msdn上对隐式类型的简单定义
从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型 var。 隐式类型的本地变量是强类型变量(就好像您已经声明该类型一样),但由编译器确定类型。
一个例子
static void Main(string[] args)
{
//隐式类型 implicitly typed
var i = ;
//显示类型 explicitly typed
int j = ;
Console.WriteLine(i.ToString());
Console.WriteLine(j.ToString());
Console.ReadKey();
}
从上面msdn上的解释,隐式类型本地变量是强类型的,由编译器确定类型,那么我们编译一下该项目,然后使用ILspy反编译查看该程序集,看看是不是将i定义为了int类型,以解心中的迷惑。
你会发现,在编译之后,变量该是什么类型就是什么类型,感觉好牛逼的样子。
那到底那些情况下可以用var?在不知道返回的到底是什么类型的时候,var的用处非常大,还有就是如果返回值类型非常长,写var也是比较轻松的,但有的时候你想真真切切看到到底是什么类型的时候,这个时候就不要用var了。再看一个例子:
//该方式返回一个匿名类,这个时候不知道用什么类型来接受,就用var
var custQuery = from cust in customers
where cust.City == "Phoenix"
select new { cust.Name, cust.Phone };
如果要遍历上面的结果,此时也必须是var,也就有了类似下面的代码
foreach(var item in custQuery)
{
//逻辑代码
}
自动属性
首先看MSDN的说法
在 C# 3.0 和更高版本中,当属性的访问器中不需要其他逻辑时,自动实现的属性可使属性声明更加简洁。 客户端代码还可通过这些属性创建对象。
这就话有点意思,“当属性的访问器中不需要其他逻辑时”,那这就话另外一个意思是,如果访问器中需要其他逻辑时,就不使用自动属性。
一个例子
如果有这样一个Person类,对年龄加了限制,年龄不得小于0,不得大于100,此时如果使用自动属性,逻辑无法添加了。如:
class Person
{
private int age;
public int Age
{
set
{
if (age > && age <= )
{
age = value;
}
else
{
throw new Exception("年龄必须在1~100范围内");
}
}
get { return age; }
}
public string Name { set; get; }
}
那么定义的自动属性,编译器又替咱们做了那些工作呢?反编译一下看个究竟
看来编译器为咱们做了很多工作。
初始化器
最常用到的初始化器有对象初始化器和集合初始化器,数组初始化器。还以上面的Person类为例:
c#3.0之前的做法是
Person p = new Person();
p.Name = "wolfy";
p.Age = ;
现在又多了一种新的玩法,对象初始化器,你现在可以这样写:
在写完大括号后,只需要一个空格,所有的属性就会智能提示出来,而且编写一个就会少一个属性,避免了多个属性的混淆。
相比之前的做法
如果一个类的字段很多,由于基类object的属性及方法的干扰,上下键的去找属性,实在是太麻烦了。通过对象初始化器,你写一个少一个,也避免出现了少为属性赋值的情况了。
那么对象初始化器,编译器又为我们做了什么?同样还是反编译一下看一个究竟
代码:
Person p = new Person() { Name="wolfy", Age= };
反编译查看的结果:
集合初始化器
代码
List<Person> persons = new List<Person>()
{
new Person(){ Age=, Name="张三"},
new Person(){Age=,Name="李四"}
};
反编译查看的结果:
的确够智能了,不能忍了,编译器替你一个一个去Add了。
数组呢?
代码
Person[] persons = new Person[]{
new Person(){ Name="张三", Age=},
new Person(){ Name="李四" , Age=}
};
看来内部并没什么变化。
匿名类
同样查看MSDN的定义
匿名类型提供了一种方便的方法,可用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型。 类型名由编译器生成,并且不能在源代码级使用。 每个属性的类型由编译器推断。
匿名类型通常用在查询表达式的 select 子句中,以便返回源序列中每个对象的属性子集。
匿名类型包含一个或多个公共只读属性。 包含其他种类的类成员(如方法或事件)为无效。 用来初始化属性的表达式不能为 null、匿名函数或指针类型。
有了匿名类类型可以这样写代码
var v = new { age = , name = "wolfy" };
Console.WriteLine(v.age + " " + v.name);
反编译看一下IL
通过上面IL,也可以说明为什么不能赋值为null,这样编译器就无法推断它到底是什么类型了。
匿名类的属性是只读的,无法修改
如果不为匿名类中的属性指定名称,则采用初始化这些属性时所采用的属性的名称作为匿名类的属性名称,看一个例子
通常,当你使用匿名类型来初始化变量时,可以通过使用 var 将变量作为隐式键入的本地变来变量进行声明。 类型名称无法在变量声明中给出,因为只有编译器能访问匿名类型的基础名称。
一个例子
//可通过将隐式键入的本地变量与隐式键入的数组相结合创建匿名键入的元素的数组
var anonArray = new[] { new { name = "apple", diam = }, new { name = "grape", diam = }};
匿名类型是直接从对象派生的类类型,并且其无法强制转换为除对象外的任意类型。 虽然你的应用程序不能访问它,编译器还是提供了每一个匿名类型的名称。 从公共语言运行时的角度来看,匿名类型与任何其他引用类型没有什么不同。
如果程序集中的两个或多个匿名对象初始值指定了属性序列,这些属性采用相同顺序且具有相同的名称和类型,则编译器将对象视为相同类型的实例。 它们共享同一编译器生成的类型信息。
无法将字段、属性、时间或方法的返回类型声明为具有匿名类型。 同样,你不能将方法、属性、构造函数或索引器的形参声明为具有匿名类型。 要将匿名类型或包含匿名类型的集合作为参数传递给某一方法,可将参数作为类型对象进行声明。 但是,这样做会使强类型化作用无效。 如果必须存储查询结果或者必须将查询结果传递到方法边界外部,请考虑使用普通的命名结构或类而不是匿名类型。
由于匿名类型上的 Equals 和 GetHashCode 方法是根据方法属性的 Equals 和 GetHashCode 定义的,因此仅当同一匿名类型的两个实例的所有属性都相等时,这两个实例才相等。
总结
本文通过反编译的方式,学习了隐式类型,自动属性,初始化器一级匿名类型的相关概念。常见的c#语法糖,在一起总结了。
参考文章
http://msdn.microsoft.com/zh-cn/library/bb383973.aspx
http://msdn.microsoft.com/zh-cn/library/bb384054.aspx
http://msdn.microsoft.com/zh-cn/library/bb397696.aspx
Linq之隐式类型、自动属性、初始化器、匿名类的更多相关文章
-
linq和隐式类型var
隐式类型 var 强类型,声明的时候必须给变量赋值,编译器会根据值来确定其类型.只能出现在局部变量或脚本代码中. 使用范围: 简单类型:如int string等 复杂类型:如数组.类等 逻辑语句:fo ...
-
C#3.0新特性:隐式类型、扩展方法、自动实现属性,对象/集合初始值设定、匿名类型、Lambda,Linq,表达式树、可选参数与命名参数
一.隐式类型var 从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型var.隐式类型可以替代任何类型,编译器自动推断类型. 1.var类型的局部变量必须赋予初始值,包括匿名 ...
-
C#3.0新增功能03 隐式类型本地变量
连载目录 [已更新最新开发文章,点击查看详细] 从 Visual C# 3.0 开始,在方法范围内声明的变量可以具有隐式“类型”var. 隐式类型本地变量为强类型,就像用户已经自行声明该类型,但 ...
-
.NET中那些所谓的新语法之一:自动属性、隐式类型、命名参数与自动初始化器
开篇:在日常的.NET开发学习中,我们往往会接触到一些较新的语法,它们相对以前的老语法相比,做了很多的改进,简化了很多繁杂的代码格式,也大大减少了我们这些菜鸟码农的代码量.但是,在开心欢乐之余,我们也 ...
-
C#的隐式类型、匿名类型、自动属性、初始化器
1.隐式类型 1)源起 在隐式类型出现之前,我们声明一个变量时,需要为它指定相应的类型,甚至在foreach一个集合的时候,也要为遍历的集合元素,指定变量的类型,隐式类型出现后,程序员就不用再做这个工 ...
-
C#中的自动属性、隐式类型var、对象初始化器与集合初始化器、扩展方法
1.自动属性(Auto-Implemented Properties) //以前的写法 .net2.0 private string _userName; public string UserName ...
-
C#语法糖之第一篇:自动属性&;隐式类型
今天给大家分享一下C#语法糖的简单的两个知识点吧. 自动属性:在 C# 4.0 和更高版本中,当属性的访问器中不需要其他逻辑时,自动实现的属性可使属性声明更加简洁. 客户端代码还可通过这些属性创建对象 ...
-
c#4.5新语法--自动属性和隐式类型
1.自动属性 自动属性是c#中属性定义的两种形式的一种:传统属性定义.自动属性. 1.1 传统属性定义 private int _age; public int ...
-
C#中的隐式类型var——详细示例解析
从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型var.隐式类型可以替代任何类型,它的具体类型由编译器根据上下文推断而出. 下面就让我来总结下隐式类型的一些特点: 1.va ...
随机推荐
-
js高级程序设计(七)BOM
window 对象 BOM 的核心对象是window,它表示浏览器的一个实例.在浏览器中,window 对象有双重角色,它既是通过JavaScript 访问浏览器窗口的一个接口,又是ECMAScrip ...
-
Socket编程基础——无连接UDP
与面向连接的网络连接相比,无连接的网络通信不需要在服务器与客户端之间建立连接.面向非连接的Socket通信是基于UDP的,服务器端不需要调用listen()和accept()函数来等待客户端的连接:客 ...
-
Android开源库--Asynchronous Http Client异步http客户端
如果说我比别人看得更远些,那是因为我站在了巨人的肩上. github地址:https://github.com/loopj/android-async-http Api文档地址:http://loop ...
-
SQL SERVER 2008 R2 SP3 发布
今晚上刚发现,微软很低调啊 下载地址:http://www.microsoft.com/zh-cn/download/details.aspx?id=44271 整合SP3的Express系列版本还没 ...
-
一天一个Java基础——数组
一天一个变成了几天一个,最近接受的新东西太多.太快,有好多需要blog的但没有时间,这些基础知识应该是要深挖并好好研究的,不应该每次都草草了事,只看个皮毛. 数组: JVM将数组存储在一个称为堆(he ...
-
java中的基本数据类型的转换
本文参考了如下两篇文章: https://my.oschina.net/joymufeng/blog/139952 http://www.cnblogs.com/lwbqqyumidi/p/37001 ...
-
实现ajax的步骤
实现ajax的步骤 1.创建xmlHttprequest对象 function createXmlHttpRequest(){ var xmlHttp; try{ //Firefox, Opera 8 ...
-
jsp标签jsp:setProperty用法
<jsp:setProperty>用来设置已经实例化的Bean对象的属性 第一种形式: <jps:setProperty name = "JavaBean实例名" ...
-
Android开发者的Anko使用指南(四)之Layouts
为什么不使用xml绘制Andoird的UI? 类型不安全 非空不安全 xml迫使你在很多布局中写很多相同的代码 设备在解析xml时会耗费更多的cpu运行时间和电池 最重要的时,它允许任何代码重用 简单 ...
-
.Net分布式锁
项目中一般使用lock作为锁,以便于多线程操作确保库内数据统一.但是如果分布式部署项目,则这种锁就是去了意义,这时可以使用redis或memcache的add方法作为分布式锁. 栗子