C#1语言核心基础
本部分将重点讨论C#1语言中的几个核心基础,他们包括:委托、类型系统、值/引用类型
1.委托
委托类似与函数指针,是要在恰当的时间执行的一系列操作,如果代码想要执行操作,但不知道操作细节,就可以使用委托。
简单委托的构成
要执行一个委托必须满足一下4个条件
-
申明委托类型
-
创建一个方法包含要执行的代码
-
创建一个委托实例
-
调用委托实例
合并和删除委托
上面的例子委托实例都只是一个操作,但是真实情况要稍微复杂一些,委托实例实际有一个操作列表与之关联,这就是调用列表。
System.Delegate类型的静态方法Combine和Remove负责创建新的委托实例,Combine负责将两个委托实例的调用列表连接到一起,而Remove负责从一个委托实例中删除另一个实例的调用列表。
在C#代码中一般很少显示调用,Combine一般使用+或者+=操作符;而Remove一般使用-或者-=操作符。
调用委托实例时所有的操作都是按顺序执行,如果委托的签名具有非void返回值,这Inovke的返回值是最后一个值的返回值。如果调用列表中任何一个方法抛出异常,都会阻止执行后续的操作。
事件
事件和委托直接差异十分大,事件不是委托类型的字段。之所以会产生混淆是因为C#提供一种简写方式,允许使用字段风格的事件(C#编译器提供的语法糖)
event<委托类型> 事件名
{
Add{ //将函数注册到自己定义的委托实例 }
Remove{ //解除函数对自己定义的委托实例的注册 }
}
总结
-
委托封装了包含特殊返回类型和一组参数的行为,类似包含单一方法的接口;
-
委托类型声明中所描述的类型签名决定哪个方法可以用于创建委托实例,同时决定调用的签名;
-
为了创建委托实例,需要一个方法以及调用方法的目标;
-
委托实例是不易变的;
-
每个委托实例都包含一个调用列表(一个操作列表)
-
委托实例可以合并到一起,也可以从一个委托实例中删除另一个;
-
事件不是委托实例,只是成对的add/reamove方法
C#的类型系统
C#1的类型系统是静态的、显式的和安全的
-
静态类型和动态类型
动态类型可能具有多种形式,动态类型的实质是变量中含有值,但那些值并不限定特定的类型,所以编译器不能执行相同形式的检查。C#4引入了动态类型,但是大多数C#4应用程序还是静态类
- 显示类型和隐式类似
显示类型和隐式类型的区别只有在静态类型的语言中才有意义。
显示类型每个变量的类型都必须在声明中显示指明 string s="hello";
隐式类型则允许编译器根据变量的用途来推断变量的类型(var 类型推断) var s="hello"
- 类型安全和类型不安全
类型安全:C#语言,CLR强制类型转换,不正确时会抛出异常,不允许直接操作内存等
类型不安全:C和C++语言,允许直接进行数据转换,操作内存,设备指针等。功能强大但是容易出错
总结
-
C#1是静态的、显示的、安全的
-
静态类型任然不允许一个集合成为强类型的"字符串列表"或者"整数列表",除非针对不同的元素使用大量的重复代码
-
方法覆盖和接口实现不允许协变性/逆变性
Linq是C#3的核心,Linq是关于查询的,其目的是使用一致的语法和特性,以一种易阅读、可组合的方式,使对多数据源的查询变得简单。
值类型与引用类型
值类型:类似只有一份儿报纸,为了给朋友一份,需要影印报纸的全部内容并交给他,届时他拥有一份完整且与原本的没有关系的报纸。
引用类型:类似正在读一个网页,相比于报纸你只需要将URL地址发个朋友,两人读取的内容相同,URL就代替引用。
.Net 中大多数都是引用类型,其中常见的引用类型有:class、数组、枚举、委托、接口;常见值类型 int double float bool struct等。
误区
-
结构体是轻量级的类
-
引用类型保存在堆上,值类型保存在栈上
引用类型的实例数据是保存在堆,但是值类型不一定保存在栈上,如果一个类中有值类型,那么该值类型也应该在堆上创建
-
对象在C#中默认是通过引用传递的
引用类型变量的值是引用,而不是对象本身。不需要按引用来传递参数本身,就可以更改参数引用的那个对象内容。引用类型作为方法参数使用时,参数默认是以"值传递"方式来传递的,但值本身是一个引用。
装箱和拆箱
装箱:将值类型转换为引用类型
拆箱:将引用类型转换为值类型
总结
-
对于引用类型的表达式,它的值是一个引用,而非对象,引用类似URL,允许你访问真实信息的一小片数据
-
对于值类型的表达式,他的值是实际数据
-
有时值类型比引用类型更有效,有时恰好相反
-
引用类型的对象总是在堆上,值类型的值既可能在栈上,也可能在堆上
4.基于C#1基础之上的新特性
与委托有关特性
C#2中与委托有关的新特性:
泛型(泛型委托类型)
创建委托实例时使用的表达式
匿名方法
委托协变性/逆变性
C#3中与委托有关的新特性:
Lambda表达式
与类型系统有关特性
C#2中与系统类型有关的特性
泛型
受限的委托协变性/逆变性
C#3中与系统类型有关的特性
匿名类型
隐式类型
扩展方法
C#4中与系统类型有关的特性
受限的泛型协变/逆变
动态类型
与值类型有关特性
C#2中与值类型有关的特性
泛型
可空类型(可以为null的类型)