15.C#回顾及匿名类型(八章8.1-8.5)
2015-01-07 22:07
134 查看
今天的篇幅应该会很长,除了回顾前面学的一些,还有写一些关于匿名类型的相关知识,总体上对后续的学习很有帮助,学好了,后面更容易理解,不明白的,那就前面多翻几次,看多了总是会理解的。那么,进入正题吧。
自动实现属性
我们的很多工作都是由编译器帮我们去完成,如我们要说的自动实现属性。使用自动实现属性时,C#3执行了一个简单的编译转换,在类的内部生成一个私有的字段,使用不友好的命名(防止命名冲突)。在C#2中允许为取值和赋值方法指定不同的访问权限,现在我们还可以创建静态的自动属性。
隐式类型
使用隐式类型,在编写代码时,没有显式地声明类型,但在编译的结果中,编译器会获取初始化表达式的类型,使用变量也具有该类型。隐式类型只有在以下几种情况才能使用:
被声明的变量是一个局部变量,而不是一个静态字段和实例字段
变量声明的同时需要初始化
初始化表达式不能是方法组,也不是匿名函数
初始化表达式不是null
语句中只声明了一个变量
初始化表达式不能包含正在使用的变量
初始化
一种方法是使用无参的构造函数先实例化一个对象,然后分别为每个公开的属性赋值。另一种则是在构造函数中将属性值作为参数,在构造函数中为每个属性赋值,这里可以给公开和私有的赋值。使用自动实现属性,则可以使用对象初始化器,如下,三个类Computer、Mouse、User
上述三个类都没有构造函数(有一个默认的无参构造函数),使用对象初始化器就能很方便的去实例化对象。
可以看到上述的每一个对象实例都使用了对象初始器来实例化对象,调用的构造函数都是系统默认的构造函数,当我们将无参的构造函数设置为私有时,上述语句将无效。那我们就可以想像,当有一个为Cup赋值的构造函数,则在new Computer(cupName)接大括号"{}"来初始化对象,如
注:调用无参的构造函数时,使用省略类名后面的括号。
是不是看上面的代码不断是很多,那我们可以再精简一下new List<User>,和new Mouse。
我们直接将类型名称给去除了,看到这里是否也想到可以把new User也给去除了,不过我试过是不行的,应该是无法确定要转换的类型吧。这个有点类似在C++11中统一使用"{}"来初始化对象。关于集合初始化可以参照上述中的对属性Users的初始化,而上述中Mouse = { Brand = "罗技" }则称呼为初始化嵌入对象。
隐式类型的数组
在C#1和C#2中,数组的声明和初始化如下
如果一个方法的签名如下:
那使用大括号中的表达式不能作为参数传入该方法,如
必须要告诉编译器传入的数组是什么类型的数组,如
但如果我们显式的指定类型,可以让编译器自己推断,则用到了隐式类型数组,里面也有涉及到协变性,如果A继承于B,参数为A的数组,那么我们使用隐式类型的数组,就可以传入A实例和B实例的数组。如:
匿名类型
匿名类型常用作用于LINQ中返回一系列的没有具体类型名的对象,也可以使用单独使用(在不想创建多余的类时)。
接下来,就可以使用变量p,p有两个属性Name="a"和Age=12,也可以使用匿名类型来初始化数组,如
匿名类型包含以下成员:
一个获取所有初始值的构造函数
公有的只读属性
属性的私有字段
重写了由object中继承的方法
关于投影初始化程序,简单地理解从一个集合中,抽取集合元素中的各别属性,组成一个匿名类型,从而返回一个包含匿名类型的集合,这也是为什么我们使用var关键字,因为我们真的不知道返回的类型,使用var让编译器替我们理解返回类型,那问题来了,这个匿名类型的声明是否由编译器帮我们生成?它帮我们生成了类型,使用反编译工具就能知晓。
请斧正。
自动实现属性
我们的很多工作都是由编译器帮我们去完成,如我们要说的自动实现属性。使用自动实现属性时,C#3执行了一个简单的编译转换,在类的内部生成一个私有的字段,使用不友好的命名(防止命名冲突)。在C#2中允许为取值和赋值方法指定不同的访问权限,现在我们还可以创建静态的自动属性。
隐式类型
使用隐式类型,在编写代码时,没有显式地声明类型,但在编译的结果中,编译器会获取初始化表达式的类型,使用变量也具有该类型。隐式类型只有在以下几种情况才能使用:
被声明的变量是一个局部变量,而不是一个静态字段和实例字段
变量声明的同时需要初始化
初始化表达式不能是方法组,也不是匿名函数
初始化表达式不是null
语句中只声明了一个变量
初始化表达式不能包含正在使用的变量
初始化
一种方法是使用无参的构造函数先实例化一个对象,然后分别为每个公开的属性赋值。另一种则是在构造函数中将属性值作为参数,在构造函数中为每个属性赋值,这里可以给公开和私有的赋值。使用自动实现属性,则可以使用对象初始化器,如下,三个类Computer、Mouse、User
class Computer { public string Cpu { get; set; } public Mouse Mouse { get; set; } public List<User> Users { get; set; } } class Mouse { public string Brand { get; set; } } class User { public string Name { get; set; } }
上述三个类都没有构造函数(有一个默认的无参构造函数),使用对象初始化器就能很方便的去实例化对象。
Computer c = new Computer() { Cpu = "AMD", Mouse = new Mouse() { Brand = "罗技" }, Users = new List<User> { new User() {Name="小A" }, new User() {Name="小B" }, new User() {Name="小C" } } };
可以看到上述的每一个对象实例都使用了对象初始器来实例化对象,调用的构造函数都是系统默认的构造函数,当我们将无参的构造函数设置为私有时,上述语句将无效。那我们就可以想像,当有一个为Cup赋值的构造函数,则在new Computer(cupName)接大括号"{}"来初始化对象,如
class Computer { public string Cpu { get; set; } public Mouse Mouse { get; set; } public List<User> Users { get; set; } public Computer(string cpu) { this.Cpu = cpu; } public Computer() { } } Computer c1 = new Computer("AMD") { Mouse = new Mouse() { Brand = "罗技" }, Users = new List<User> { new User() {Name="小A" }, new User() {Name="小B" }, new User() {Name="小C" } } };
注:调用无参的构造函数时,使用省略类名后面的括号。
是不是看上面的代码不断是很多,那我们可以再精简一下new List<User>,和new Mouse。
Computer c1 = new Computer("AMD") { Mouse = { Brand = "罗技" }, Users = { new User() {Name="小A" }, new User() {Name="小B" }, new User() {Name="小C" } } };
我们直接将类型名称给去除了,看到这里是否也想到可以把new User也给去除了,不过我试过是不行的,应该是无法确定要转换的类型吧。这个有点类似在C++11中统一使用"{}"来初始化对象。关于集合初始化可以参照上述中的对属性Users的初始化,而上述中Mouse = { Brand = "罗技" }则称呼为初始化嵌入对象。
隐式类型的数组
在C#1和C#2中,数组的声明和初始化如下
string[] names = { "a", "b", "c" };
如果一个方法的签名如下:
public void Method0(string[] names)
那使用大括号中的表达式不能作为参数传入该方法,如
Method0({ "a", "b", "c" });
必须要告诉编译器传入的数组是什么类型的数组,如
Method0(new string[] { "a", "b", "c" });
但如果我们显式的指定类型,可以让编译器自己推断,则用到了隐式类型数组,里面也有涉及到协变性,如果A继承于B,参数为A的数组,那么我们使用隐式类型的数组,就可以传入A实例和B实例的数组。如:
class A { } class B : A { } public static void Method1(A[] args) { } A a = new A(); B b = new B(); Method1(new[] { a, b }); Method1(new[] { new A(), new B() });
匿名类型
匿名类型常用作用于LINQ中返回一系列的没有具体类型名的对象,也可以使用单独使用(在不想创建多余的类时)。
var p = new { Name = "a", Age = 12 };
接下来,就可以使用变量p,p有两个属性Name="a"和Age=12,也可以使用匿名类型来初始化数组,如
var ps = new[] { new { Name = "a", Age = 12}, new { Name = "a", Age = 12}, new { Name = "a", Age = 12} };
匿名类型包含以下成员:
一个获取所有初始值的构造函数
公有的只读属性
属性的私有字段
重写了由object中继承的方法
关于投影初始化程序,简单地理解从一个集合中,抽取集合元素中的各别属性,组成一个匿名类型,从而返回一个包含匿名类型的集合,这也是为什么我们使用var关键字,因为我们真的不知道返回的类型,使用var让编译器替我们理解返回类型,那问题来了,这个匿名类型的声明是否由编译器帮我们生成?它帮我们生成了类型,使用反编译工具就能知晓。
请斧正。
相关文章推荐
- 匿名类型—C#基础回顾
- 匿名类型
- Javascript基础回顾 之(一) 类型
- WebAPI 返回匿名类型
- Unity中C#高级特性匿名类型使用
- 对象初始化器、集合初始化器、自动属性、匿名类型
- C#3.0亮点 —— 关键字var和匿名类型
- 从异常{ 无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型 }说开去
- Java基础知识回顾之一 ----- 基本数据类型
- 8.1 shell介绍 8.2 命令历史 8.3 命令补全和别名 8.4 通配符 8.5 输入输出重
- 为什么匿名内部类参数必须为final类型
- C#3.0学习(3)---匿名类型
- C#之匿名类型与隐式局部变量
- 微软免费图书《Introducing Microsoft LINQ》翻译Chapter2.1:C# 3.0 特性(对象初始化表达式\匿名类型\查询表达式)
- C#基础回顾之1——值类型与引用类型
- 匿名类型&&堆和栈
- C#3.0 中 隐式类型变量、匿名类型
- 为什么匿名内部类参数必须为final类型
- [C#基础知识]专题十三:全面解析对象集合初始化器、匿名类型和隐式类型 推荐