《C#入门经典(第五版)》学习笔记

时间:2021-03-09 20:00:32

仅用于个人记录学习笔记,入坑C#。Vas‘y!


2016.1.16

第一部分 第一章 C#简介

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

公共语言运行库(Common Language Runtime,CLR)

 本机代码(native code)

编译为通用中间语言代码(Common Intermediate Language,CIL)

ust-In-Time(JIT)编译器

全局程序集缓存(Global Assembly Cache,GAC)

垃圾回收(garbage collection)

Active Server Pages .NET(ASP.NET)


第三章 变量和表达式

用#region 和#endregion 关键字,来定义可以展开和折叠的代码区域的开头和结尾

PascalCase 和camelCase

@逐字指定的字符串字

char 变量实际上存储的是数字,所以把两个char 变量加在一起也会得到一个数字(其类型为int)。

secondNumber = Convert.ToDouble(Console.ReadLine());


第四章 流程控制

&& || 逻辑 短操作符, & | 长操作符 或 按位操作

case 语句实际上是在C#代码中定义的标签

常量关键字const 最初赋值后不能改变

用户输入有效性检查


第五章 变量的更多内容

bool 和 String 没有隐式转换

checked unchecked 表达式溢出检查上下文

Convert.ToSingle(Console.ReadLine());  显示转化为 float 

Convert 类型转换 总要进行溢出检查

枚举、结构、数组

enum <typeName> : <underlyingType>
{
<value1> = <actualVal1>,
<value2> = <actualVal2>,
<value3> = <actualVal3>,
<valueN> = <actualValN>
}


foreach 循环

foreach (<baseType> <name> in <array>)
{
// can use <name> for each element
}

多维数组 <baseType>[,] <name>;  与 数组的数组 int[][] jaggedIntArray 不同


第六章 函数

参数数组 C#允许函数制定一个特殊的参数 params 关键字  params <type>[] <name>

引用参数 ref  关键字   ref参数 需要初始化且可在函数中更改(不能为const)

输出参数 out  关键字

执行方式与引用参数相同,在函数执行完毕后,该参数的值将返回给调用函数中使用的变量。

把为赋值的变量用作 ref 是非法的 但可以用作 out

在使用out 参数时, out参数必须看作为赋值


  在函数调用中 要使用 ref  out 关键字


Main() 返回值 为int 时,通常用作错误提示,0为正常

参数args 是从应用程序的外部接受信息的方法,这些信息在运行期间指定,其形式是命令行参数。

结构可以有结构函数


委托

delegate 关键字,把变量 声明为一种函数,来代替其他函数

委托类型可以匹配返回类型和参数与委托定义相同的方法

使用委托可以把一个排序算法函数委托传递给排序函数,指定要使用的方法。

大多常见通途与事件处理有关


第七章 调试与错误处理


调试信息输出

Debug.WriteLine()       Trace.WriteLine()

Debug 只在调试阶段,不会生成。在发布版本中自动消失


错误处理

try
{
...
}
catch (<exceptionType> e)
{
...
}
finally
{
  没有异常 总会执行的代码
}

需要重新再好好看下这一章!!!!!


第八章 面向对象编程简介


统一建模语言(Unified Modeling Language,UML)

1.对象数据信息存储在字段或属性中,属性不提供对数据的直接访问。

属性    读/写访问    访问权限

字段设为私有,通过公共属性来访问

在UML中 属性或字段没有区别 

可访问性,+号表示公共成员,-号表示私有成员。但一般情况下,本章的图中不显示私有成员,因为这些信息是类内部的信息。至于读/写访问,则不提供任何信息。
成员名。
成员的类型。

冒号用于分隔成员名和类型。


2.方法用于访问对象的功能 

在 UML 的对象框中,方法显示在第三部分  显示的类型是返回类型

在UML 中,每个参数都带有下述标识符之一:in、out 或inout。它们用于表示数据流的方向,其中
out 和inout 大致对应于第6 章讨论的C#关键字out 和ref。in 大致对应于C#中不使用这两个关键字的情形。


C#和.NET Framework 中的所有东西都是对象


对象生命周期  : 构造阶段 构造函数        析构阶段  删除对象 释放内存


所有的类定义都至少包含一个构造函数 用new 关键字来调用构造函数。


.NET Framework 使用析构函数清理对象 一般情况自动执行操作。超出范围 必须执行垃圾回收 才能彻底删除。


静态成员  可以在类的实例之间共享。可以使用静态属性跟踪给类创建了多少个实例

静态字段与属性,可以访问独立于任何对象实例的数据,

静态方法法可以执行与对象类型相关、但与对象实例无关的命令

在使用静态成员时,甚至不需要实例化对象。


在UML 语法中,类的静态成员用下划线表示


初始化静态成员,使用类静态构造函数

一个类只有一个静态构造函数,没有访问修饰符,没有参数。静态构造函数不能直接调用,

 创建包含静态构造函数的类实例时
 访问包含静态构造函数的类的静态成员时

这两种情况 先调用静态构造函数


静态类,不用于实例化。

静态类只能包含静态成员,不需要构造函数,可以有一个静态构造函数。


接口是把公共实例(非静态)方法和属性组合起来,以封装特定功能的一个集合。一且定义了接口,

就可以在类中实现它。这样,类就可以支持接口所指定的所有属性和成员。

1.不能实例化

2.只定义成员,不实现成员代码。实现过程在实现接口的类中完成

接口的名称一般用大写字母I 开头

是把接口看作类的创建者和使用者之间的契约

应创建一个新的接口,来扩展旧接口,例如包含一个版本号,如X2。这是创建接口的标准方式.


在UML 中,在对象上实现的接口用“棒棒糖”语法来表示


可删除对象,实现IDisposable 接口的对象必须实现其Dispose()方法,不再使用某个对象时,调用方法,释放资源。

C#中可以使用using关键字来初始化重要资源对象,代码库结束 自动调用Dispose()方法。

<ClassName> <VariableName> = new <ClassName>();

using (<VariableName>){

...

}

或者把初始化时象<VariableName>作为using 语句的一部分:
using (<ClassName> <VariableName> = new <ClassName>()){

...

}


C#中的对象仅能直接派生于一个基类,当然基类也可以有自己的基类。

派生类不能访问基类私有成员,但可以访问 公共成员。private

派生类和外部类的代码都可以访问公共成员。public

protected  外部类不能访问,派生类可以。


抽象类、抽象函数。必须继承来使用。 抽象类可以提供现实代码。

抽象方法只能存在于抽象类中

类可以密封(seal) 密封的类不能被继承,

共同基类 System.Object


接口可以继承接口,接口可以继承多个基接口。


在UML 中,用箭头表示继承。抽象类名以斜体显示(有时它们的方框有一个短横线)。


多态性

直接调用派生类方法,需要强制类型转换为派生类变量

接口的多态性  (接口不包含实现代码)

建立接口类型的变量,然后就可以在支持该接口的对象上,使用这个变量访问该接口提供的方法和属性。


派生类会继承基类支持的接口。


对象之间


包含关系containment

包含类可以控制对被包含类的成员的访问,甚至在使用被包含类的成员前进行其他处理。


与集合关系

一个类用作另一个类的多个实例的容器。这类似于对象数组,但集合有其他功能,包括索引、排序和重新设置大小等。


在UML 中,被包含类可以用关联线条来表示。对于简单的包含关系,可以用带有1 的线条说明一对一的关系。

为清晰起见,也可以把被包含的Udder 类实例表示为Cow 类的私有字段,


集合关系它们通常以所存储的对象名称的复数形式来命名,例如类Animals 就包含Animal 对象的个集合。


UML中 连接线末尾的数字表示一个Animals 对象可以包含0 个或多个Animal 对象。



变量的类型分为两种:
引用类型和值类型

值类型在内存的一个地方存储它们自己和它们的内容。

可以使用可空类型(这是泛型的一种形式)创建一个值类型,使值类型在这个方面的行为方式类似于引用类型(即可以为null)。

引用类型存储指向内存中其他某个位置(称为堆)的引用,而在另一个位置存储内容。


string 和object 简单类型是引用类型,数组也是隐式的引用类型

类都是引用类型


结构类型和类的重要区别是,结构类型是值类型。



第九章 定义类


 class 关键字

内部的 internal  只有当前项目中的代码才能访问,默认情况 类是内部的。

公共类 public 可以由其他项目中的代码来访问。

类不能是私有或保护的,类成员可以。


抽象类 互斥关键字 abstract 抽象类 或 sealed 密封类

在C#的类定义中,只能有一个基类,如果继承了一个抽象类,就必须实现所继承的所有抽象成员(除非派生类也是抽象的)

编译器不允许派生类的可访问性高于基类。也就是说,内部类可以继承于一个公共基类,但公共类不能继承于一个内部类。

如果没有使用基类,则被定义的类就只继承于基类System.Object(它在C#中的别名是object)。


类:基类名或接口

所有接口成员都必须在支持该接口的类中实现,

但如果不想使用给定的接口成员,就可以提供一个个“空”的实现方式(没有函数代码)。

还可以把接口成员实现为抽象类中的抽象成员。


基类必须是继承列表的第一项,  用“,”分隔。 可以指定多个接口。


接口的定义

interface 关键字

有public 和 internal  没有sealed和abstract

接口可以用 : 继承其他接口


System.Object

typeof(这是一个C#运算符,可以把类名转换为System.Type 对象)

在.NET 中使用的析构函数(由System.Object 类提供)叫作Finalize()   使用~MyClass()  而不是重写Finalize()


构造函数初始化器  可以在派生类的构造函数定义中指定所使用的基类构造函数

public MyDerivedClass(int i, int j) : base(i)
{
}

base 关键字 指定.NET 实例化过程使用基类中有指定参数的构造函数。

this 关键字  指定在调用指定的构造函数前,.NET 实例化过程对当前类使用非默认的构造函数。

如果没有给构造函数指定构造函数初始化器,编译器就会自动添加base(),执行默认构造函数


接口和抽象类


抽象类和接口都包含可以由派生类继承的成员。

接口和抽象类都不能直接实例化,但可以声明这些类型的变量。


派生类只能继承一个基类,即只能直接继承一个抽象类(但可以用一个继承链包含多个抽象类)。相反,类可以使用任意多个接口。


抽象类可以拥有抽象成员(没有代码体,且必须在派生类中实现,否则派生类本身必须也是抽象的)与非抽象成员(它们拥有代码体,也可以是虚拟的,这样就可以在派生类中重写)。

接口成员必须都在使用接口的类上实现——它们没有代码体。


接口成员是公共的但抽象类的成员可以是私有的


接口不能包含字段、构造函数、析构函数、静态成员或常量。


抽象类主要用作对象系列的基类,共享某些主要特性,例如,共同的目的和结构。
接口则主要用于类,这些类在基础水平上有所不同,但仍可以完成某些相同的任务。


使用指针的全部技术隐藏在托管C#代码中,它使得代码更简单。使用C#中的不安全代码可以进行低级操作,如指针操作.


浅度复制(shallow copy),深度复制(deep copy)

可以实现一个ICloneable 接口,以标准的方式来进行。包含Clone()方法


第十章 定义类成员


访问级别

public——成员可以由任何代码访问。
private——成员只能由类中的代码访问(如果没有使用任何关键字,就默认使用这个关键字)。
internal——成员只能由定义它的程序集(项目)内部的代码访问。
protected——成员只能由类或派生类中的代码访问。

protected internal 成员只能由项目(更确切地讲,是程序集)中派生类的代码来访问。

关键字static 来声明字段、方法和属性,这表示它们是类的静态成员


字段

.NET Framework 中的公共字段以PascalCasing 形式来命名

私有字段没有推荐的命名模式,它们通常使用camelCasing 来命名。

用关键字readonly,表示这个字段只能在执行构造函数的过程中赋值,或由初始化赋值语句赋值。

关键字const 来创建一个常量,是静态的。


方法

与公共字段一样,.NET Framework 中的公共方法也采用PascalCasing 形式来命名

static 关键字,这个方法就只能通过类来访问,不能通过对象实例来访问。

virtual——方法可以重写。
abstract——方法必须在非抽象的派生类中重写(只用于抽象类中)。
override——方法编写了一个基类方法(如果方法被重写,就必须使用该关键字)。
extern——方法定义放在其他地方。


如果使用了override,也可以使用sealed 指定在派生类中不能对这个方法作进一步的修改,即这个方法不能由派生类重写

public override sealed void DoSomething()
{
// Derived class implementation, overrides base implementation.
}


属性

并不直接修改状态,用get 和 set 

访问器,分别用get 和set 关键字来定义,可以用于控制对属性的访问级别。

可以忽略其中的一个块来创建只读或只写属性(忽略get 块创建只写属性,忽略set 块创建只读属性)。

属性的基本结构包括标准的可访问修饰符(public、private),后跟类名、属性名和get 块(或set
块,或者get 块和set 块,其中包含属性处理代码),例如:
public int MyIntProp
{
get
{
// Property get code.
}
set
{
// Property set code.
}
}

.NET 中的公共属性也以PascalCasing 方式来命名

关键字value 表示用户提供的属性值: myInt = value;

属性可以使用virtual、override 和abstract 关键字

访问器可以有自己的可访问性,但访问器的可访问性不能高于它所属的属性

自动属性 public int MyIntProp { get; set; }


隐藏基类

new 关键字


调用重写或隐藏的基类方法

base 关键字

this 关键字


接口

不允许使用访问修饰符(public、private、protected 或internal),所有的接口成员都是公共的。
接口成员不能包含代码体。
接口不能定义字段成员。
接口成员不能用关键字static、virtual、abstract 或sealed 来定义。
类型定义成员是禁止的。


要隐藏继承了基接口的成员,可以用关键字new

在接口中定义的属性可以定义访问块get 和set 中的哪一个能用于该属性


接口与类一样,可以定义为类的成员(但不能定义为其他接口的成员,因为接口不能包含类型定义)。


可以使用关键字virtual 或abstract 来实现接口成员,但不能使用static 或const。还可以在基类上实现接口成员


在基类中把实现代码定义为虚拟,派生类就可以替换该实现代码,而不是隐藏它们。


显示实现接口成员

用非公共的可访问性添加属性存取器

但是,只有所添加的存取器的可访问修饰符比接口中定义的存取器的可访问修饰符更严格才可以


部分类定义(partial class definitions)

partial 关键字

部分方法 partial void MyPartialMethod();

部分方法也可以是静态的,但它们总是私有的,且不能有返回值。

它们使用的任何参数都不能是out 参数,但可以是ref 参数。

部分方法也不能使用virtual、abstract、override、new、sealed 和extern修饰符。



第十三章 其他OOP技术


::运算符 使编译器使用由using 语句定义的别名

::运算符还可以和global 关键字一起使用,它实际上是*根名称空间的别名。

global::System.Collections.Generic.List<int>


throw new exception 定制异常


事件

事件类似于异常,因为它们都由对象引发(抛出),我们可以提供代码来处理事件。

必须订阅(subscribe)它们,事件处理程序

对事件处理方法的唯一限制是它必须匹配于事件所要求的返回类型和参数。

这个限制是事件定义的一部分,由一个委托指定。