C#图解教程

一、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字符的可变数组。会分配一个比当前字符串长度更长的缓冲区,只要能容纳就不会分配新的内存。如果空间不够,就分配更大的缓冲区,并把字符串拷贝到其中。

原文地址:https://www.cnblogs.com/wwhhgg/p/12845398.html