一、C#和.NET框架
CIL(Common Intermediate Language)公共中间语言
CLR(Common Language Runtime)公共语言运行库
BCL(Base Class Library)基类库
JIT(Just-in-Time)编译器
managed code托管代码
.NET框架由两部分组成:公共语言运行库和基类库,即CLR和FCL(框架类库,是BCL的超集,包括Windows Forms、ASP.NET LINQ以及更多命名空间)。
CLR在运行期管理程序的执行:内存管理、代码安全验证、代码执行、垃圾收集。
BCL和FCL包括:通用基础类(比如字符串操作、安全和加密)、集合类(实现列表、字典、散列表以及位数组)、线程和同步类(创建多线程)、XML类(用于创建、读取以及操作XML文档)
.NET语言编译器接受源代码文件,并生成程序集的输出文件。程序集可以是可执行文件或DLl。程序集里的代码不是本机代码,而是CIL公共中间语言。
程序CIL直到调用运行时才会被编译成本机代码。在运行时,CLR执行:
检查程序集的安全特性、在内存中分配空间、把程序集的可执行代码发送给JIT编译器,把其中的一部分编译成本机代码。
- 托管代码:为.NET框架编写的代码
- 非托管代码:不在CLR控制之下运行的代码,比如Win32C/C++ DLL
.NET框架的核心组件是CLR,在操作系统的顶层并管理程序的执行。并提供下列服务:自动垃圾收集、安全和认证、通过访问BCL得到广泛编程功能。
二、C#编程概述
三、类型、存储和变量
C程序是一组函数和数据类型,
C++程序是一组函数和类,
C#是一组类型声明。类型声明包括:名称、结构、行为。
- 值类型:只需要一段单独的内存,用于存储实际的数据,可以在堆也可以在栈。
- 引用类型:需要两段内存:一段存储实际的数据,始终位于堆中;二段是一个引用,指向数据在堆中的存放位置。
对于引用类型的任何对象,它所有的数据成员都存放在堆里,无论它是值类型还是引用类型。
四、类:基础
访问修饰符:私有(private)、公有(public)、保护(proteced)、内部(internal)、受保护内部(proteced internal)
五、方法
常量const:声明中必须初始化;声明后不能改变。
ref:引用与实参相同的内存位置,即传进去的是地址,会改变值。
out:要先赋值,然后在方法里对该地址的值进行改变。
params:参数数组,允许多个实参对应一个特殊的形参。
六、类进阶
const修饰符:只能在字段声明语句中初始化,值在编译期决定
readonly修饰符:可以在任意位置初始化,值在运行期决定
this关键字:在类中使用,是对当前实例的引用,静态成员不是实例的一部分,所以静态函数成员不能使用this。
this被用于下列目的:区分类的成员和本地变量,或参数;作为调用方法的实参。
七、类和继承
除了类object,所有的类都是派生类。访问基类用关键字base.
派生类的实例由基类的实例加上派生类附加的成员组成。派生类的引用指向整个类对象,包括基类部分。
当使用基类引用访问派生类对象时,得到的是基类的成员。虚方法可以使基类的引用访问派生类内。virtual override
派生类使用一个指定的基类构造函数而不是无参构造函数,必须在构造函数初始化语句中指定它:1、使用关键字base,2、使用关键字this。
public myClass(int x):base(s,x)
myClass() 等价于 myClass():base()
程序集指该命名空间namespace
抽象类:只能被用作其它类的基类,就是被设计来被继承的。不能创建抽象类的实例;用abstract修饰符声明;可以派生自另一个抽象类;派生自抽象类的类必须使用override实现该类所有的抽象成员。
密封类:只能被用作独立的类,不能被用作基类;用sealed修饰符。
静态类:用static修饰符;所有成员必须是静态;是密封的;
外部方法:external method是在声明中没有实现的方法,常常是c#之外的语言编写的。
八、表达式和运算符
无后缀的实数字面量是double类型,不是float类型。
typeof运算符:Type t = typeof(someClass),Type是System命名空间中的一个类。t.GetFields()获取变量列表;t.GetMethods()获取方法列表;GetType().Name获取类的名字。
九:语句
break:跳出最内层封装的语句
continue:转到最内层封装循环的顶端
using:某些类型的非托管对象有数量限制或很耗费系统资源,using可以确保这些资源被适当地处置。资源是一个实现System.IDisposable接口的类或结构。Dispose方法:分配资源、使用资源、处置资源。
using会隐式产生try,finally,块。在finally中会调用Dispose来处置资源。
十、命名空间和程序集
程序集:不包括本地机器代码,而是公共中间语言代码。包含实时编译器JIT在运行时转换CIL到本机代码所需的一切,包括对它所引用的其它程序集的引用。程序集的文件扩展名通常为.exe或.dll。
十一、异常
十二、结构
结构:是值类型,类是引用类型;结构是隐式密封的,所以不能被派生。
十三、枚举
枚举:是值类型,命名的整数值常量。
十四、数组
数组:是引用类型,由一个变量名称表示的一组同类型的数据元素。一旦被创建,大小就固定,C#不支持动态数组。
数组实例是从System.Array继承的对象。数组是引用类型,但是数组元素可以是值类型或引用类型。
3×3的矩形数组以及一个由三个长度为3的一维数组构成的交错数组的结构。
1、两个数组都保存了9个整数,但是它们的结构却很不相同。
2、矩形数组只有单个数组对象,而交错数组有4个数组对象。
foreach:迭代变量是临时的,只读的,并且和数组中元素的类型相同。
Clone:为数组进行浅复制,克隆值类型数组会产生两个独立数组;克隆引用类型数组会产生指向相同对象的两个数组类型。
十五:委托
委托:delegate可以认为是包含具有相同签名和返回值类型的有序方法列表,当委托被调用时,它调用列表中的每一个方法。委托是面向对象的并且是类型安全的。
调用列表中的方法可以是实例或是静态方法。
调用委托可以像调用方法一样,最后一个方法执行的返回值是委托返回的值
匿名方法转换成lambda表达式
十六、事件
事件event:与委托相似,事件就好像被简化的针对特殊用途的委托。注册到事件上的方法会在事件触发时被调用。事件包含一个私有的委托。
触发(raise)事件:调用(invoke)或触发(fire)事件。
十七、接口
接口interface:引用类型,表示一组函数成员而不实现成员的引用类型,类和结构可以实现接口。接口可以多继承,类只能单继承。
从类对象引用获取接口引用,然后使用接口引用调用方法。用as来获取。
十八、转换
转换conversion:声明两个不同类型的变量,然后把一个变量(源)的值赋值给另外一个变量(目标)。
隐式转换:不会丢失数据或精度
显式转换:可能会引起丢失数据
装箱:把引用类型转换到object,把值类型转换到System.ValueType
装箱:在堆分配好内存;将值类型字段复制到堆内存中;返回对象的地址,也就是对象的引用。
返回了副本的值的引用类型,装箱后,有两份值-原始值类型和副本的引用类型。
拆箱:显式转换,把装箱后的对象转换回值类型的过程。检测到要拆箱的对象实际是ValueType的装箱值,把对象的值复制到变量。
值类型转换:
占据较少位的可以隐式转换为多位的数字类型
unchecked:会忽略溢出
checked:抛出OverflowException异常
引用类型转换:
is 运算符:来检查转换是否会成功完成。只可以用于引用转换以及装箱和拆箱转换。
as运算符:和强制转换运算符类似,如果转换失败,把目标引用设置为null而不是抛出异常。只能用于引用转换和装箱转换。不支持用户自定义或值类型的转换。
十九:泛型
泛型:不是类型,而是类型的模板。C#提供5种泛型:类、结构、接口、委托和方法。
泛型和非泛型区别:
Where:约束泛型的范围。
二十:枚举数和迭代器
数组可以迭代是因为数组可以按需提供一个枚举数的对象,枚举数可以依次返回请求的数组的元素。枚举数“知道”项的次序并且跟踪它在序列中的位置,然后返回请求的当前项。
foreach结构被设计和可枚举类型一起使用。
枚举数类型:IEnumerator/IEnumerable接口 非泛型接口
IEnumerator<T>/IEnumerable<T>接口 泛型接口
IEnumerator接口包含三个函数成员: Current、 MoveNext以及Reset。
Current返回序列中当前位置项的属性。
MoveNext是把枚举数位置前进到集合中下一项的方法。它也返回布尔值,指示新的位置是有效位置或已经超过了序列的尾部。
Reset方法把位置重置为原始状态。
二十一:介绍LINQ
Linq(Language Integrated Query语言集成查询)是集成到C#和Visual Basic.NET这些语言中用于提供查询数据能力的一个新特性。是.NET框架的扩展,允许我们以数据库查询的方式查询数据集合。C#3.0引入。
XML
二十二、异步编程简介
启动一个程序时,系统在内存中创建一个新的进程(process)。
进程:就是一组资源,构成了一个正在运行的程序。这些资源包括虚拟地址空间、文件句柄以及程序启动需要的其它东西的载体。
线程:在进程中,系统创建一个叫线程(thread)的内核对象,体现了一个程序的真实执行情况。一旦程序准备完毕,系统在线程中开始执行Main方法的第一条语句。
线程重要事项:
1、默认情况下,一个进程只包含一个线程,从程序开始到结束
2、一个线程可以发起另外一个线程,一个进程可能在不同状态有多个线程来执行程序不同部分
3、如果一个进程中有多个线程,它们会分享进程的资源
4、线程是由系统负责调度的处理器(而不是进程)上的执行单元
同步编程:程序的进程只有一个线程,并且语句是顺序执行的
异步编程:程序发起多个线程,理论上是同一个时间执行的(其实不一定真的在同一时间执行)
在多核处理器的系统,不同线程可能在不同的处理器上同时执行,可以提高性能。
多线程处理:增加程序的负荷和额外复杂度。例如:
1、创建和销毁线程都有时间和资源的成本
2、安排线程、把它们加载到处理器中以及每次时间片段之后保存状态都需要时间
3、由于进程中的线程共享相同的资源和堆,需要增加额外的编程复杂度来确保它们之间不相干扰
4、调试多线程非常困难,因为程序每次运行的时间不同可能会产生不同的结果
多线程处理复杂度:
1、线程之间通信:同一进程的所有线程来说,内存是可见也是可访问的
2、协调线程:线程之间的执行顺序
3、同步资源使用:进程内所有线程共享相同的资源和内存,要确保不同线程没有同一时间访问和改变它们引起冲突的状态
C#中委托就是一个简单的机制用于异步执行方法。运用BeginInvoke,EndInvoke实现异步执行。有下面三种用法:
二十三、预处理指令
源代码指定了程序的定义。预处理指令(preprocessor directive)指示编译器如何处理源代码。
二十四、反射和特性
大多数程序是用来处理数据的,读、写、操作和显示数据,而有时候操作的数据不是数字、文本或图形,而是程序和程序类型本身的信息。
1、有关程序及其类型的数据称为元数据(metadata),它们保存在程序的程序集中。
2、程序在运行时,可以查看其它程序集或其本身的元数据,这个查看行为就叫反射。
Type抽象类,被设计用来包含类型的特性,使用这个类的对象能获取程序使用的类型的信息。创建一个类时,CLR会创建一个Type抽象类的对象。
Type对象的获取:使用GetType方法和 typeof运算符
特性(attribute)是一种允许我们向程序的程序集增加元数据的语言。它是用于保存程序结构信息的某种特殊类型的类。
特性的目的是告诉编译器把程序结构的某组元数据嵌入程序集。
二十五:其它主题
1、字符串:是Unicode字符串数组,是不可变的(immutable)不能被修改。
对于一个string任何“改变”都会分配一个新的恒定字符串。
StringBuilder:可以产生能被修改的字符串,是Unicode字符的可变数组。会分配一个比当前字符串长度更长的缓冲区,只要能容纳就不会分配新的内存。如果空间不够,就分配更大的缓冲区,并把字符串拷贝到其中。