2023年12月30日发(作者:)

本文档是学习《C#高级编程》第七版的读书笔记,对于一些资源参考了网络相关文章。本文档仅供个人学习,不可用于商业行为。

第Ⅰ部分

部分 C#语言C#语言

语言

第一章

第一章 .NET体系结构

1. 什么是 .NET Framework?

2. C#语言和 .NET Framework关系是什么?

3. 什么是公共语言运行库?

4. 什么是托管代码? 其与非托管代码有什么不同? 他们执行效率如何?

5. IL是什么?

6. 什么是程序集?

7. 值类型和引用类型的区别?

答1:.NET Framework是用于Windows的新托管代码编程模型。 .NET Framework又称 .Net框架。一个致力于敏捷软件开发(Agile software developmentAgile software development)、快速应用开发(Rapid Rapid

Agile software developmentapplication development)、平台无关性和网络透明化的软件开发平台。 .NET框架是以application development一种采用系统虚拟机运行的编程平台,以通用语言运行库(Common Language RuntimeCommon Language Runtime)为Common Language Runtime基础,支持多种语言(C#、VB、C++、Python等)的开发。

答2:C#本身只是一种语言,尽管它是用于生成面向.NET环境的代码,但它本身不是.net的一部分。.net支持的一些特性,C#并不支持。而C#语言支持的另一些特性,.net却不支持。 但C#语言是和.NET一起使用的,所以如果要使用C#高效地开发应用程序,理解Framework就非常重要。

答3:.NET Framework的核心是其运行库的执行环境, 称为公共语言运行库公共语言运行库( CLR) 或 .NET运行库。

CLR和Java虚拟机一样也是一个运行时环境,它负责资源管理(内存分配和垃圾收集),并保证应用和底层操作系统之间必要的分离.

在 .NET中,编译分为两个阶段:

(1)

(1) 把源代码编译为Microsoft中间语言(IL)。

(2) CLR把IL编译为平台专用的代码。

(2)

CLR带有三个不同的JIT编译器

(1)(1) 缺省的编译器---主编译器

(2)(2) PREJIT,它建立在主JIT编译器之上

(3)(3) ECONOJIT,在并不充分优化的前提下,它能够快速完成IL代码到本地码的转(3)换,编译速度与运行速度都非常快。

答4: .Net Framework 是由彼此独立又相关的两部分组成:CLRCLR 和 类库, CLR是它为我类库

们提供的服务,类库是它实现的功能.

.NET的大部分特性----垃圾收集,版本控制,线程管理等,都使用了CLR提供的服务。 当你为 .Net Framework 编译源代码的时候,得到的目标代码不是CPU能识别的机器指令,而是一种叫做"微软中间语言(MSIL,或简称为IL的代码)"的新语言. CLR 提供了一个实时编译器, 用来把 IL 代码编译为本机机器代码. 这样一来,CLR 能够使代码变得可移植, 因为 .NET 应用程序的源代码必须被编译为 IL 代码,这些IL代码可以运行在任何提供CLR 服务的平台上. 从CLR 的角度来看,所有的语言都是平等的,只要有一个能生成 IL代码的编译器就行, 这就确保了各种语言的互操作性.

为CLR而编写以及使用CLR服务的代码叫"托管代码托管代码",而那些未使用CLR服务的代码托管代码(也就是你多年以来一直编写的代码)叫"非托管代码非托管代码".

非托管代码 讨论到C++在 .NET托管环境中的应用,由于C++不是为.NET平台设计的语言,所以,微软需要对C++作一些扩充,这就引入了"托管扩展"这一概念,它允许我们在C++项目中使用.NET Framework,如果有下列开发需要,就必须使用托管扩展:

1. 将现有的C++代码移植到托管环境中

2. 在C++代码中访问 .NET Framework类

3. 通过.NET语言访问现有的C++代码

程序的加载过程:

(1)(1) 这个函数在一个叫做MSCorEE .dll的动态链接库文件中,当安装了.net框架时就会被复制在系统目录下。

(2)(2) 系统会根据托管程序PE文件中的信息找到这个DLL,

(3)(3) 然后通过MSCorEE .dll的PE文件信息找到这个_CorExeMain函数的入口地址,

(4)(4) 然后修改刚才的JMP指令要跳转的地址,从而将控制跳转到了_CorExeMain这个函数里面去。

(5)(5) 然后,在这个函数里面,CLR被启动了,并做了若干的初始化工作,

(6)(6) 然后再通过托管程序的CLR表头找到托管程序的入口地址,并将控制跳转到这里,

(7)(7) 于是托管程序开始运行

注:Visual C++可以创建非托管程序。当你创建一个项目,并且选择名字以MFC,ATL或者Win32开头的项目类型,那么这个项目所产生的就是非托管程序

当你创建一个托管的 C++ 程序, 那么构建出来的是一个中间语言程序集和一个扩展名为 .exe 的可执行文件。 当你创建一个MFC 程序, 构建出来是一个 Windows 原生代码的可执行文件, 这个文件的扩展名也是 .exe。这两个文件的内部结构是完全不一样的。

【参考】浅析托管与非托管C++代码

/view/maguschen/23927?from_com

【参考】托管代码与非托管代码的执行效率比较

/blog/visit_article_?article_id=1871&u_id=05070201

/housisong/article/details/1486504

【参考】 托管代码与非托管代码之间的封送处理

/zh-cn/magazine/

答5:Microsoft中间语言(Microsoft Intermediate Language,MSIL或简称为IL) ,重要的优点:平台无关性、提高性能和语言的互操作性

中间语言的主要特征:

(1)

(1) 面向对象和使用接口

(2) (2) 值类型和引用类型之间的巨大差别

(3)

(3) 强数据类型

(4) (4) 使用异常来处理错误

(5)

(5) 使用特性(attribute)

答6:程序集(assembly)是包含编译好的、面向 .NET Framework的代码的逻辑单元.

程序集 程序集程序集(assembly)是一个或多个托管模块,以及一些资源文件的逻辑组合。

程序集 程序集是组件复用,以及实施安全策略和版本策略的最小单位。

程序集程序集是包含一个或者多个类型定义文件和资源文件的集合。

程序集 程序集有两种类型:共享程序集共享程序集和私有程序集共享程序集私有程序集。

私有程序集 【参考】 C#之程序集 /ruixj/article/details/1299813

注:

Windows DNAWindows DNA Windows DNA是Windows Distributed interNet Applications

Architecture 的缩写,Windows 分布式集成网络应用体系结构

CTSCTS

CTS 通用类型系统(Common Type System)

CLSCLS

CLS 公共语言规范(Common Language Specification)

CLRCLR 公共语言运行时(Common Language Runtime)

跨平台的 .NET运行环境 Mono / 下图是MONO的体系结构图

CTS(Common Type System)(通用类型系统) :描述了类型的定义和行为。

1. CTS规范规定一个类型可以包含0个或多个成员。

2. CTS规范定义了类型可见性和访问类型成员的一些规则。

CTS建立了以程序集作为类型可见性边界的规则。而CLR实现了这种可见性规则。

3. 所有的类型都必须继承自System .Object。

托管模块是一个需要CLR才能够执行的标准Windows可移植可执行文件。托管模块(portalbe executable 简称PE)。

组成部分

PE 表头

描述

标准的 Windows PE 文件表头,类似于通用对象文件格式 (Common

Object File Format ,简称COFF) 表头。 该表头指出了文件的类型: GUI( 图像用户界面) , CUI(控制台用户界面 ),或者 DLL( 译即 Dynamic Link 注:DLL 在以前表示 Windows中的动态链接库文件,

Library ,它是以动态链接的方式提供的一组函数库。在 .net 平台中, 由于和传统的动态链接库文件有着相同的扩展名 .dll , 所以 DLL 文件的名称被沿用了下来,但其含义已经有所改变。 .NET中的 DLL 特指程序集文件的一种形式 )另外该表头还包括一个时间标记用于表示文件创建的时间。对于仅包含 IL代码的模块,该表头的大多数信息会被忽略。对于包含有本地 CPU 代码的模块,该表头还会包含有关本地 CPU 代码的一些信息。

CLR 表头 包含标识托管模块的一些信息 (可以被 CLR 或者一些实用工具解析 )。这些信息包括托管模块所需要的 CLR 版本号,一些标记,托管模块入口点方法 (Main 方法) 的 MethodRef元数据标记,以及有关托管模块的元数据、资源、强命名、标记和其他一些意义不是太大的信息的位置和尺寸

每个托管模块都包含一些源数据表。元数据表主要分两种,一种用于描述源代码中定义的类型和成员,一种用于描述源代码中引用的类型和成员

元数据

中间语编译器在编译源代码时产生的指令。 CLR 在运行时会将IL 代码编言 (IL) 代码 译成本地 CPU 指令

如上图,可知.NET的下述特性在编译和执行过程中的作用:

· 程序集和.NET基类

· COM组件

· JIT编译

· 应用程序域

· 垃圾收集

答7:参考第三章

运行环境

运行环境

是 .net 用来编译 .cs文件的,但必须要在安装目录下使用。 所以我们要设置一下环境变量。

C#环境变量设置:

1、在桌面右击[我的电脑]->[属性]->[高级]->[环境变量]

2、在下面的系统变量栏点击“新建”

3、变量名输入“csc”

4、变量值输入: “C:meworkv1.1.4322” (2000是C:meworkv1.1.4322)

5、然后在系统变量列表框中双击“Path”

6、在变量名文本框的最后面加入“;%csc%”

解决设置环境变量两种方法

1) Microsoft Visual Studio 8Common7Tools

2) 开始|程序|Microsoft Visual Studio XXXX|Microsoft Visual Studio Tools 启动命令提示窗口 (自动运行)

【参考】 的环境变量设置

/blog/static/1198337200/

第二章

第二章 核心C#

C#

声明变量

变量的初始化和作用域

C#的预定义数据类型C#的预定义数据类型

在C#程序中使用循环和条件语句指定执行流C#程序中使用循环和条件语句指定执行流

枚举

命名空间

Main()方法Main()方法

基本的命令行C#编译器选项C#编译器选项

使用e执行控制台I/O

使用注释和文档编制功能

预编译器指令

C#编程的推荐规则和约定C#编程的推荐规则和约定

C#有两个方法可确保变量在使用前进行了初始化C#有两个方法可确保变量在使用前进行了初始化:

有两个方法可确保变量在使用前进行了初始化 (1) 变量是类或结构中的字段,如果没有显式初始化,创建这些变量时,其值就默认是0。(2) 方法的局部变量必须在代码中显式初始化,之后才能在语句中使用它们的值。

此时,初始化不是在声明该变量时进行的,但编译器会通过方法检查所有可能的路径,如果检测到局部变量在初始化之前就使用了它的值,就会产生错误。

Something objSomething;

//在C++中,上面的代码会在堆栈中创建Something类的一个实例

//在C#中这行代码仅会为Something对象创建一个引用,但这个引用还没有指向任何对象

在C#中实例化一个引用对象需要使用new关键字

objSomething = newnew Something(); // This creates a Something on the heap 创new建一个Something对象并存储在堆上

类型推断:类型推断:var

var

(隐含类型局部变量

隐含类型局部变量 C#3.0引进了var这个新关键字)这个新关键字)

· 变量必须初始化。否则,编译器就没有推断变量类型的依据。

· 初始化器不能为空

· 初始化器必须放在表达式中

· 不能把初始化器设置为一个对象,除非在初始化器中创建一个新的对象

int someNumber = 0; 等同于 var someNumber = 0;

注:变量必须初始化,声明了变量,推断出了类型后,变量的类型就不能改变了

常量:const常量:const

在声明和初始化变量时,在变量的前面加上关键字const,就可以把该变量指定为一个const常量。

在C++中,变量不仅可以声明为常量,而且根据声明,还可以有常量指针、指向常量的变量指针、常量方法(不改变包含对象的内容)、方法的常量参数等。这些细微的特性在C#中都删除了,只能把局部变量和字段声明为常量。

常量具有如下特征:

常量具有如下特征(1) 常量必须在声明时初始化。指定了其值后,就不能再修改了。

(2) 常量的值必须能在编译时用于计算。

因此,不能用从一个变量中提取的值来初始化常量。如果需要这么做,应使用只读字段。

(3) 常量总是静态的。但注意,不必(实际上,是不允许)在常量声明中包含修饰符static。

使用常量的好处:

使用常量的好处(1) 常量用易于理解的清楚的名称替代了含义不明确的数字或字符串,使程序更易于阅读。

(2) 常量使程序更易于修改。

如果要把另一个值赋给程序中的一个常量,而该常量已(3) 常量更容易避免程序出现错误。经有了一个值,编译器就会报告错误。

C#把数据类型分为两种:

· 值类型值类型 存储在堆栈中

值类型· 引用类型引用类型 存储在托管堆中

引用类型C#中的值类型基本上等价于Visual Basic或C++中的简单类型(整型、浮点型,但没有指针或引用)

C#中的引用类型与Visual Basic中的引用类型相同,与C++中通过指针访问的类型类似。

如果变量是一个引用,就可以把其值设置为null,表示它不引用任何对象.

把基本类型(如int和bool)规定为值类型值类型,而把包含许多字段的较大类型(通常在有类值类型的情况下)规定为引用类型引用类型,C#设计这种方式的原因是可以得到最佳性能。如果要把自己的引用类型类型定义为值类型,就应把它声明为一个结构

C#认可的基本预定义类型并没有内置于C#语言中,而是内置于.NET Framework中。

C#有15个预定义类型,其中13个是值类型(整型、浮点类型、decimal类型、bool类型、字符类型),2个是引用类型(string和object)。

整型

整型 (8个)

名 称

sbyte

short

int

long

CTS 类 型

16

32

64

说 明

8位有符号的整数

16位有符号的整数

32位有符号的整数

64位有符号的整数

范 围

–128~127 (–27~27–1)

–32 768~32 767 (–215~215–1)

–2 147 483 648~2 147 483 647(–231~231–1)

–9 223 372 036 854 775 808~9 223

372 036 854 775 807(–263~263–1)

0~255(0~28–1)

0~65535(0~216–1)

0~4 294 967 295(0~232–1)

0~18 446 744 073 709 551

615(0~264–1)

byte

ushort

uint

ulong

注:

16

32

64

8位无符号的整数

16位无符号的整数

32位无符号的整数

64位无符号的整数

在C#中,int总是32位带符号的整数,而在C++中,int是带符号的整数,但其位数取决于平台(在Windows上是32位)。

在C#中,所有的数据类型都以与平台无关的方式定义,以备将来C#和.NET迁移到其他平台上。

C#认为byte类型和char类型完全不同,它们之间的编程转换必须显式写出。还要注意,与整数中的其他类型不同,byte类型在默认状态下是无符号的,其有符号的版本有一个特殊的名称sbyte。

sbyte所有整数类型的变量都能赋予十进制或十六进制的值,后者需要0x前缀。 long x

= 0x0x12ab

0xuint ui = 1234UU; long l = 1234LL; ulong ul = 1234ULUL;UL

浮点类型(浮点类型(2个)

名称

float

double

CTS 类 型

说明

32位单精度浮点数

64位双精度浮点数

位 数

7

15/16

范围(大致)

±1.5 × 10-45~±3.4 ×

1038

±5.0 × 10-324~±1.7

× 10308

float数据类型用于较小的浮点数,因为它要求的精度较低。double数据类型比float数据类型大,提供的精度也大一倍(15位)

float f = 12.3FF

decimal类型 (1个)表示精度更高的浮点数 可用于财务计算 用法:decimal d = 12.30M

类型

名称 CTS 类 型 说明 位数 范围(大致)

±1.0×10-28~±7.9

× 1028

true或false

decimal l 128位高精度十进制数表示法 28

bool类型 类型 (1个)

名称

bool

名称

char

CTS 类 型

n

CTS 类 型

说明

表示true或false

表示一个16位的(Unicode)字符

位数

NA

字符类型

字符类型 (1个)

C++的char表示一个8位字符,而C#的char包含16位. C#本身有一个string类型,所以不需要把字符串表示为char类型的数组。

转义符

转义符

转 义 序 列

'

"

0

a

b

f

n

字 符

单引号

双引号

反斜杠

警告

退格

换页

换行

r

t

v

引用类型

引用类型名 称

object

string

回车

水平制表符

垂直制表符

CTS 类

说 明

根类型,CTS中的其他类型都是从它派生而来的(包括值类型)

Unicode字符串

object类型就可以用于两个目的:类型就可以用于两个目的

·可以使用object引用绑定任何子类型的对象。object引用也可以用于反射,此时必须有代码来处理类型未知的对象。这类似于C++中的void指针或Visual Basic中的Variant数据类型。

·object类型执行许多一般用途的基本方法,包括Equals()、GetHashCode()、GetType()和ToString()。用户定义的类需要使用一种面向对象技术-- 重写(见第4章),提供其中一些方法的替代执行代码。

string类型

类型

string filepath = "C:";

string filepath = @"C:";

流控制

流控制C#中,if子句中的表达式必须等于布尔值;

C#中的if语句不能直接测试整数(例如从函数中返回的值),而必须明确地把返回的整数转换为布尔值true 或 false。

C#中,switch语句的一个有趣的地方是case子句的排放顺序是无关紧要的,甚至可以把default子句放在最前面

C#提供了4种不同的循环机制(for、while、do...while和foreach)

foreach循环可以迭代集合中的每一项。集合是一种包含其他对象的对象。从技术上看,循环集合要使用集合对象,就必须支持IEnumerable接口。集合的例子有C#数组、tion命名空间中的集合类,以及用户定义的集合类.

枚举

枚举在C#中,枚举的真正强大之处是它们在后台会实例化为派生于基类的结构.

Q:如何从字符串获取枚举值,并转换为整数?

A:要从字符串中转换,需要使用静态的()方法,这个方法带3个参数,第一个参数是要使用的枚举类型,其语法是关键字typeof后跟放在括号中的枚举类名。第二个参指定在进行转换时是否忽略大小写。最后,第三个参数是一个bool,数是要转换的字符串,注意()方法实际上返回一个对象引用-- 我们需要把这个字符串显式转换为需要的枚举类型(这是一个拆箱操作的例子)

命名空间

命名空间

命名空间与程序集无关。同一个程序集中可以有不同的命名空间,也可以在不同的程序集中定义同一个命名空间中的类型

C#允许简写类的全名。为此,要在文件的顶部列出类的命名空间,前面加上using关键字

因为using语句在C#文件的开头,C和C++也把#include语句放在这里,所以从C++迁移到C#的程序员常把命名空间与C++风格的头文件相混淆。不要犯这种错误,using语句在这些文件之间并没有建立物理链接。C#也没有对应于C++头文件的部分

using关键字的另一个用途是给类和命名空间指定别名

C#程序是从方法C#程序是从方法Main()开始执行的Main()开始执行的。开始执行的。这个方法必须是类或结构的静态方法,这个方法必须是类或结构的静态方法,并且其返回类型必须是int或void

程序中存在多个Main()时,可以使用/main选项,其后跟Main()方法所属类的全名(包括命名空间),明确告诉编译器把哪个方法作为程序的入口点。

Q:前面介绍了如何使用编译控制台应用程序,但其他类型的应用程序如何编译?

A:第一个问题,应使用/target选项(常简写为/t)来指定要创建的文件类型

选 项

/t:exe

/t:library

/t:module

/t:winexe

输 出

控制台应用程序 (默认)

带有清单的类库

没有清单的组件

Windows应用程序 (没有控制台窗口)

Q:如果要引用一个类库,该怎么办?

一个可由.NET运行库加载的非可执行文件(例如DLL),就必须把它编译为一个库。如果把C#文件编译为一个模块,就不会创建任何程序集。虽然模块不能由运行库加载,但可以使用/addmodule选项编译到另一个清单中。

选项是/out,该选项可以指定由编译器生成的输出文件名。如果没有指定/out选项,编译器就会使用输入的C#文件名,加上目标类型的扩展名来建立输出文件名(例如.exe表示Windows或控制台应用程序,.dll表示类库)。注意/out和/t(或/target)选项必须放在要编译的文件名前面。

默认状态下,如果在未引用的程序集中引用类型,可以使用/reference或/r选项,后跟程序集的路径和文件名

字符串

C

D

E

F

G

N

P

说 明

本地货币格式

十进制格式,把整数转换为以10为基数的数,如果给定一个精度说明符,就加上前导0

科学计数法(指数)格式。精度说明符设置小数位数(默认为6)。格式字符串的大小写("e"或"E")确定指数符号的大小写

固定点格式,精度说明符设置小数位数,可以为0

普通格式,使用E 或 F格式取决于哪种格式较简单

数字格式,用逗号表示千分符,例如32,767.44

百分数格式

X 十六进制格式,精度说明符用于加上前导0

XML文档说明

文档说明标 识 符

说 明

把行中的文本标记为代码,例如int i = 10;

把多行标记为代码

标记为一个代码示例

说明一个异常类(编译器要验证其语法)

包含其他文档说明文件的注释(编译器要验证其语法)

把列表插入到文档说明中

标记方法的参数(编译器要验证其语法)

表示一个单词是方法的参数(编译器要验证其语法)

说明对成员的访问(编译器要验证其语法)

给成员添加描述

说明方法的返回值

提供对另一个参数的交叉引用(编译器要验证其语法)

提供描述中的“参见”部分(编译器要验证其语法)

提供类型或成员的简短小结

描述属性

C#编程规则C#编程规则

编程规则【参考】参考】计算机-》概念规则-》C#编程规则

(本地路径目录)

第三章

第三章 对象与类型

对象与类型

类和结构的区别

类成员

按值和引用传送参数

方法重载

构造函数和静态构造函数

只读字段

部分类

静态类

Object类,其他类型都从该类派生而来

Q:类和结构的区别Q:类和结构的区别

类和结构体实际上都是创建对象的模板,每个对象都有包含数据(数据成员和函数成员的数据结构),并提供了处理和访问的方法。

与类不同的是,结构是值类型并且不需要堆分配。结构类型的变量直接包含结构的数据,而类

类型的变量包含对数据的引用(该变量称为对象)。 struct 类型适合表示如点、矩形和颜色这样的轻量对象轻量对象。轻量对象尽管可能将一个点表示为类,但结构在某些方案中更有效。在一些情况下,结构的成本较低结构的成本较低。例如,如果声明一个含有1000个点对象的数组,则将为引用结构的成本较低每个对象分配附加的内存。结构可以声明构造函数,但它们必须带参数。声明结构的默认(无

参数)构造函数是错误的。总是提供默认构造函数以将结构成员初始化为它们的默认值。在结构中初始化实例字段是错误的。在类中,必须初始化实例对象. 使用new运算符创建结构对象时,将创建该结构对象,并且调用适当的构造函数。与类不同的是,结构的实例化可以不使用 new 运算符。如果不使用 new,那么在初始化所有字段之前,字段将保持未赋值状态且对象不可用。对于结构,不像类那样存在继承。一个结构不能从另一个结构或类继承,而且不能作为一个类的基。但是,结构从基类 Object 继承。

类在堆中

类在堆中,类在堆中结构在栈中,结构在栈中类传递的是类在堆中的地址,而结构是在栈中另复制了一个传递,你改变传递过来的结构不会影响原结构。而类是引用,共用一块内存,会改变堆中类的内容.

C++中二者最大的区别就是struct的成员默认是 public,而class的成员默认是

private的

(1)值类型与引用类型(1)值类型与引用类型

结构结构是值类型:值类型在堆栈上分配地址,所有的基类型都是结构类型,例如例如:int 对结构例如应32 结构,通过使用结构可以创建更多的值类型

类类是引用类型:引用类型在堆上分配地址

堆栈的执行效率要比堆的执行效率高,可是堆栈的资源有限,不适合处理大的逻辑复杂的对象。所以结构处理作为基类型对待的小对象,而类处理某个商业逻辑

因为结构是值类型所以结构之间的赋值可以创建新的结构,而类是引用类型,类之间的赋值只是复制引用。结构在传递的时候如果没有指定ref,则传递的是内存中的一分副本,而class则是传递对他的引用。

注:

1).虽然结构与类的类型不一样,可是他们的基类型都是对象(object),c#中所有类型的基类型都是object

2).虽然结构的初始化也使用了New 操作符可是结构对象依然分配在堆栈上而不是堆上,如果不使用“新建”(new),那么在初始化所有字段之前,字段将保持未赋值状态,且对象不可用

(2)(2)继承性(2)继承性

结构结构:不能从另外一个结构或者类继承,本身也不能被继承,虽然结构没有明确的用结构sealed声明,可是结构是隐式的sealed .

类类:完全可扩展的,除非显示的声明sealed 否则类可以继承其他类和接口,自身也能被继承

注:虽然结构不能被继承可是结构能够继承接口,方法和类继承接口一样

例如:结构实现接口

(3) (3) 内部结构(3)

内部结构:内部结构:

结构结构:结构:

没有默认的构造函数,但是可以添加构造函数

没有析构函数

没有 abstract(抽象) 和 sealed(密封)(因为不能继承)

不能有protected 修饰符

可以不使用new 初始化

在结构中初始化实例字段是错误的

类类:

有默认的构造函数

有析构函数

可以使用 abstract(抽象) 和 sealed(密封)

有protected 修饰符

必须使用new 初始化

Q:如何选择结构还是类 Q:如何选择结构还是类

讨论了结构与类的相同之处和差别之后,下面讨论如何选择使用结构还是类:

(1)(1)堆栈的空间有限,对于大量的逻辑的对象,创建类要比创建结构好一些

(1) (2)(2)结构表示如点、矩形和颜色这样的轻量对象,例如,如果声明一个含有 1000 个点对(2)象的数组,则将为引用每个对象分配附加的内存。在此情况下,结构的成本较低。

(3)(3)在表现抽象和多级别的对象层次时,类是最好的选择

(3) (4)(4)大多数情况下该类型只是一些数据时,结构时最佳的选择

(4)

ref参数

参数 ref参数,是指类中一般方法的ref参数。如果一个方法的参数前带有ref关键字,则该方法对变量所作的任何改变 都会影响到原来对象的值。

注意事项:在传递给方法前,无论是值传递,还是引用传递,变量都需要初始化。

out 关键字out

关键字

关键字 在方法的输入参数前面加了out关键字时,传递给对方的变量可以不初始化。

Q:out和ref区别:区别:

ref是传递参数的地址,out是返回值,两者有一定的相同之处,不过也有不同点。

使用ref前必须对变量赋值,out不用。

out的函数会清空变量,即使变量已经赋值也不行,退出函数时所有out引用的变量都要赋值,ref引用的可以修改,也可以不修改。

方法重载方法重载

方法重载 方法重载只需声明同名但参数个数或者类型个数类型不同的方法即可

注意事项:

(1)C#重载不支持可选参数

(2)重载不能仅在返回类型上有所区别

(3)重载不能仅根据参数声明为ref还是out区别

只读字段readonly

readonly

readyonly关键字比const灵活的多,允许把一个字段设置为常量,但可以执行一些运算,来确定其初始值,其规则是可以在构造函数中给只读字段赋值,但不能在其他地方赋值。若要设置只读字段为静态,那么必须设置显式声明。

部分类部分类

部分类 partial关键字

关键字 partial关键字允许把类、结构体或接口放在多个文件中。一般类存储在一个文件中。但有时候多个开发人员需要访问同一个类,或者某种类型的代码生成器生成了一个类某部分,所以把类放在多个文件时有益的。

静态类静态类

静态类 静态类使用可以不创建实例化,就可以调静态类中的方法。

扩展方法

扩展方法 有许多方法扩展类。如果有类的源代码,继承就是给对象添加功能的好方法,但是若果没有源代码怎么办呢,这个时候我们就可以使用扩展方法啦。它允许改变一个类,但不需要改变源代码。扩展方法是静态方法,是类的一部分,但实际上没有放在类得源代码中