您的位置:首页 > 编程语言 > C#

《C#程序设计教程 -李春保》阅读笔记

2018-01-17 19:06 134 查看

《C#程序设计教程 -李春保》阅读笔记

  ( 需注意程度:红>粗体>下划线,蓝色:我的疑问 )  
  • 老师的引言 [ul] [师]对待一种新语言的关注点 [li]数据类型定义(python不用定义)
  • 语法
[/li]
  • JAVA两大优势 [li]面相对象:比C++简单
  • 跨平台
  • 开源:造就了很多免费的东西
  • [/ul] [/li]
  • 每个button其实就是类的实例
  • 找工作一定要有一技之长
  • 面试内容:
      [li]大公司:基础:C语言、数据结构
    • 小公司:技术:C#、Java
    [/li]
  • 数据传递(不确定正误):
      [li]多数据传递:静态类
    • 单数句传递:构造函数
    [/li]
  • 看懂书了再写代码
  • 1 C#语言概述
      C#: [li]完全面向对象,设计一个程序就是设计一个或多个类 最长编写的3种应用类型
    • 控制台程序
    • 窗体程序:窗体为.cs文件
    • web应用程序
    [/li]
  • 代码:
      托管代码: [li]在CLR控制下运行
    • 不能写内存
    • 是安全的
    [/li]
  • 非托管代码:
      [li]由操作系统直接运行
    • 可以使用指针操作内存(所以指针是在操作内存)
    • 不安全的
    [/li]
  • .NET Framework
      [li]FCL(Framework Class Library):全面的类库,包含大量处理常见的低级编程操作;由命名空间组成见p4-5 CLR(公共语言运行库):操作系统顶层,管理程序的执行,总的来说,包括:无用存储单元的回收,代码验证和类型安全,代码访问安全
    • CLS(Common Language Specification公共语言规范):定义了所有编程语言必须遵守的共同标准,语法
    • CTS(Common Type System通用类型系统):定义了一套预定义数据类型。如:VB中的integer和C#中的int,在编译后都映射为System.Int32,实现了不同语言数据类型的统一,从而实现跨语言功能
    [/li]
  • 运行应用程序代码的过程
  • C#与. NET Framework的关系
  • Visual C#集成开发环境
      [li]菜单
    • 工具栏:菜单中常用的按钮放到这里了,可在“视图|工具栏”自定(我也要养成自定义工具栏的思维)
    • 解决方案管理器:
    • 解决方案名称。解决方案包含项目。.slh可以打开整个项目
    • 项目:包含于解决方案
    • 引用:库函数,指出程序引用的命名空间
    • program.cs是代码文件。所有C#代码的源文件都是.cs(即C Sharp)为拓展名
    [/li]
  • 编辑器设置:在 工具|选项(虽然是在菜单的某一选项,却包含了整个软件的设置)
  • 项目的构成(目录在 资源管理器 显示)
      [li]properties:
    • 引用:指出程序引用的命名空间
    • Program.cs namespace关键字的作用(using某些方面类似于c的#include):
    • 组织代码
    • 分类管理
    • 包含多个类
    [/li]
  • 其他
      [li]Main()为程序入口 数据类型
    • 值类型:直接存储所包含的值(结构体是值类型),在栈空间分配
    • 引用类型:存的是指针,指向它所要存储的值(字符串是引用类型),其对象在堆空间分配
    [/li]
  • 2 C#程序设计基础
      变量的四个理解层面 [li]变量的名称:和该内存空间绑定在一起,对变量名称的操作就是对内存空间的操作,也就是说程序员通过变量来使用计算机的内存空间。从系统的角度看,变量就是程序中的存储单元,它既表示这块内存空间的地址,也表示这块内存空间中存储的数据。
    • 变量的值
    • 变量的数据类型:决定了可容纳什么样的值,取值范围,什么样的操作可执行
    • 变量的作用域和生命周期
    [/li]
  • 数据类型:1值类型变量的内存开销小、访问速度快; 2引用类型变量内存开销大、访问速度稍慢; 3无论值类型变量还是引用类型变量,都是在栈空间中分配对应的存储空间,所不同的是,引用类型变量所指的对象是在托管堆上分配内存空间
      值类型 [li]简单类型:[师]类型转换是一定要考虑溢出
    • 结构类型:注意结构体是值类型
    • 枚举类型
    [/li]
  • 引用类型
      类 [li]string类:@ 字符串 为严格字符串,其中无转义字符
    [/li]
  • 接口
  • 数组
  • 委托
  • 堆与栈:
      [li]栈:系统管理所有的栈空间
    • 堆:程序可在堆中保存数据,但在c#中不能显式地删除他们,因为我们没有指针,我们只管创建类的实例用就好了,CLR帮我们处理无用的对象
    [/li]
  • 其他
      [li]拆箱和装箱:即值类型和引用类型的转换
    • 结构类型:实际问题中,一组数据往往具有不同的数据类型,结构类型可以存储多个不同类型的数据(我:分类是人类认识世界的方式,所以这个也是为了归类,为了理清人类的思绪?),结构类型常规使用就是赋值和访问
    • 枚举类型:用符号代替数据,提高程序的可读性。如用X.red表示红色。枚举类型常规使用就是赋值和访问
    • 运算符:
    • new:创建对象(我:这也当作运算符看?那什么不是运算符呢?)
    • checked:启用溢出检查
    [/li]
  • 常用类:1 C#是一种纯面向对象语言,使用类和结构体来实现数据类型,而对象是给定数据类型的实例;2 C#中一切都是对象,例如,int数据类型就是一个类,它提供了相应的属性和方法,int x=3这条代码,int为类,x为对象。
      string类: [li]格式化字符串:Format()。有的函数库中就有了,不要再造轮子了
    [/li]
  • Math类:要写计算器,根本不用自己实现那些复杂算法,直接用这些函数就可以了,一定要有这种思想,不要重复造轮子
  • Convert类:值类型(?仅值类型吗?书写错了?string也可以的啊)间的转换
  • 问题:类语言和非类语言编译器的实现有什么区别?
  • 问题:静态方法和动态方法有什么区别,为什么要做这种区分?
  • 3 C#控制语句
      [li][师] if{ if..... }else{ if..... }如果有很多判断,写在黑体的if不易读,写在划线的if更易读
    • 循环控制语句:for通常用于已知循环次数(for只能用于已知循环次数,这句话是错的)
    • [师] 我(俞定国老师)当年是纸上写一遍,脑子验证,然后敲在电脑
    • break,continue用于跳出循环(故写在if中,跳出的是if外的循环)
    • 阅读代码的方法:阅读代码只看关键的,细节都忽略
    • while后的表达式为逻辑表达式或关系表达式
    [/li]
  • 4 数组和集合
      [师] c的强势在于 [li]指针
    • 位运算:直接到低层内存的运算
    [/li]
  • [师]1先写各种代码,然后向上向下拓展。2代码要分块,也就是把步骤和功能分割开
  • 数组
      [li]数组是引用类型,通过一个名称来存取,所有值放在内存的一段连续空间,为了区分不同的值,添加了一些索引或下标。
    • 集合和数组不同的地方在于:可动态增减
    • 通常把二维数组叫做矩阵
    • 数组的动态初始化(new)和静态初始化,只不过是编译时间不同,结果是一样的
    • foreach(var 迭代变量 in 数组或集合)
    • 有些情况为了简单,数组下标中的0总是不用
    [/li]
  • Array类:所有数组的抽象基类。在C#中,数组实际上是对象,而不像C/C++中那样的可寻址连续内存区域
      [li](我:对象不是 可寻址连续内存区域 ?)(我:什么是对象,什么是可寻址连续内存区域)。
    • 静态方法+动态方法
    [/li]
  • ArrayList类 [师]:重点掌握,不像C需要自己控制
      [li]Array类的优化版本,容量或元素个数不像Array是固定的
    • 可存放多重数据类型,其用的数据类型是Object
    • Array是多维的,ArrayList是一维的
    • 均非静态方法
    [/li]
  • List<T>类:是ArrayList类的泛型等效类 [师]:重点掌握,不像C需要自己控制
      [li]数据类型是指定的
    • 均为非静态方法
    • 这个有一个方法叫ForEach可以对每个元素执行指定操作
    [/li]
  • 数组、List和ArrayList的区别
      [li]数组在内存中是连续存储的,所以它的索引速度是非常的快,而且赋值与修改元素也很简单,但是数组也存在一些不足的地方。比如在数组的两个数据间插入数据也是很麻烦的,还有我们在声明数组的时候,必须同时指明数组的长度,数组的长度过长,会造成内存浪费,数组和长度过短,会造成数据溢出的错误。这样如果在声明数组时我们并不清楚数组的长度,就变的很麻烦了。C#中最先提供了ArrayList对象来克服这些缺点
    • ArrayList是数据存储和检索的专用类,大小是按照其中存储的数据来动态扩充与收缩的。因为ArrayList会把所有插入其中的数据都当作为object类型来处理。这样,在我们使用ArrayList中的数据来处理问题的时候,很可能会报类型不匹配的错误,也就是说ArrayList不是类型安全的。既使我们保证在插入数据的时候都很小心,都有插入了同一类型的数据,但在使用的时候,我们也需要将它们转化为对应的原类型来处理。这就需要装箱与拆箱的操作,会带来很大的性能损耗。(该类的方法索引均从0开始)
    • 所以在C#2.0后出现了泛型的概念。List<T>类 在声明List集合时,我们同时需要为其声明List集合内数据的对象类型。通过允许指定泛型类或方法操作的特定类型,泛型功能将类型安全的任务从您转移给了编译器。不需要编写代码来检测数据类型是否正确,因为会在编译时强制使用正确的数据类型。减少了类型强制转换的需要和运行时错误的可能性。泛型提供了类型安全但没有增加多个实现的开销。(List list = new ArrayList();这句创建了一个ArrayList的对象后把上溯到了List。此时它是一个List对象了,有些ArrayList有但是List没有的属性和方法,它就不能再用了。 而ArrayList list=new ArrayList();创建一对象则保留了ArrayList的所有属性。 )
    [/li]
  • 考试前要看一遍正确的定义数组的几种方式,否则会混淆!考后这句话就删除掉吧
  • 5 面向对象程序设计
      [li][师]:面向对象中,有20%的知识常用,就像搭积木,你只需要搞定用的东西
    • 对象之间通过一定的“相互操作”传递信息([师金哲凡]:传递消息是一种设计概念,落实到语言上就是函数调用),在消息的作用下完成特定功能。
    • 封装:尚未理解
    • C#实现运行时多态性的基础是动态方法调度,它是一种在运行时而不是在编译期调用重载方法的机制。(不能完全理解后面这句话的意义)
    • 从计算机语言角度来说,类是一种数据类型,而对象是具有这种类型的变量
    • 通常用数据成员模拟现实世界事物的特性,通常用函数成员模拟现实世界的功能和操作
    • 无修饰符时,默认为私有的
    • 类和结构类型很相似,但也有不同,主要差异如下
    • 对象浏览器和类图方便程序员进行面向对象的程序设计
    • 对象引用变量在栈空间分配,实例在堆空间分配
    • 没有引用变量指向的堆空间会被CLR收回
    • using 命名空间,注意using不是加的类,而是命名空间
    • 当定义类对象时,构造函数会被自动执行,当类对象销毁时,析构函数会自动执行
    • 自己写了含参数构造函数,记得自己写一个默认函数
    • 静态成员属于类所有,非静态成员属于类的对象所有。提出静态成员概念的目的是为了解决数据共享的问题
    • 静态和非静态的存储方式
    • 静态构造函数的特点:不会继承,在所有的构造函数中最先被执行
    • 问题:属性是强化的字段,弱化的方法,right?
    • Main()是每个C#应用程序入口,在启动时由公共语言运行库调用
    • 方法中的参数是保证不同方法间互动的重要“桥梁”,方便用户对数据进行操作
    • 方法的参数类型(注意参数是值还是引用就容易多了) 值类型
    • 在栈中为形式参数分配空间
    • 计算实参的值,并把该值复制给形式参数
    • 注意体会这张图和代码
    [/li]
  • 引用参数
      [li]不会在栈上分配空间
    • 形参将作为实参的别名
    • 注意体会这张图和代码
    [/li]
  • 输出参数
      [li]也不开辟新的内存区域
    [/li]
  • 参数数组
  • 可选参数
  • this关键字:对当前实例的引用
  • 对象的复制:非静态方法Object.MemberwiseClone()来实现
      [li]浅复制:共享除String的所有引用成员实例
    • 深复制:需自己创建新的引用类型,C#并没有嵌入在语言中
    [/li]
  • 嵌套类:未细看,用时看p119-p121
  • 索引器:类似于属性,不同在于访问器采用参数。索引类型并不限制为整数。它的引入为了使程序更加直观、易于理解。索引器的声明、使用如下:
  • 委托:即函数指针,不同于c/c++,可以与多个方法关联在一起,可以把委托对象看成一系列方法,使用. +=委托对象 .增加方法,委托封装的多个方法都会被一次性一起调用。声明与使用:
  • 事件:委托(函数指针)是事件的基础。在事件通信中,事件源类不知道哪个对象或方法将接受到(处理)它引发的事件,所需要的是在源和接收方之间存在一个媒介(或类似指针的机制)。使用与分析见下图:
  • 犯错截图:
  • 6 继承和接口设计(习题尚未做)
      继承 [li]为了对现实世界中的层次结构进行模型化,面向对象的程序设计技术引入了继承的概念
    • 派生类对象也是基类的对象,所以基类的引用变量可以引用基派生类对象(注意勿反,这两句话句话和一般的世界规律有点不同)
    • 除了构造函数和析构函数,派生类隐式地继承了基类所有成员
    • 基类的private不能被继承(待查询)
    • (问题:那上一句话是不是说错了?“除了构造函数和析构函数,派生类隐式地继承了基类所有成员”)
    • 构造函数:从最远开始调用
    • 析构函数:从最近开始调用
    • (问题:一个类只能有1个析构函数,为什么?不是可以两个吗?自己的一个,CLR默认的都有一个?)
    • 继承使得程序允许创建分等级阶层的类
    • 【师】:默认构造方法建议都写上,不要忽略
    [/li]
  • 多态性
      [li]多态性是指发出同样的消息(如方法调用)被不同类型的对象接收时可能导致不同行为
    • 隐藏基类方法:用new关键字(注意:并非直接重写,有意隐藏要用new)
    • 重写基类方法:适用情景:同一签名的方法实现相同的目标,但在不同的地方有不同的实现细节,此时就需要用虚方法实现该方法的不同细节。 调用虚方法时,首先调用派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员
    • 在基类使用virtual关键字(不能与static、abstract、override一起用)
    • 在子类使用override关键字
    [/li]
  • 一个基类对象引用变量可以指向其子类的对象(记忆方法:父亲可以指着儿子(骂))
  • is运算符:检查是否为该类型或可以转换为制定类型
  • as运算符:在兼容的引用类型之间执行转换
  • 易混的重写和重载对比
      [li]重载:同一个类,同一个方法的多种形式,签名不同
    • 重写:父子类, 同一个方法重写, 签名相同
    [/li]
  • 抽象类
      [li]一个类不与具体的事物相联系,而是表达一种抽象的概念,仅仅作为其派生类的一个基类
    • 派生抽象类的非抽象子类必须实现所有抽象方法和抽象访问器
    • 尚未理解内容(下方):
    • 其他注意事项:
    [/li]
  • 接口
      [li]接口是类之间交互内容的一个抽象,把类之间需要交互的内容抽象出来定义成接口,可以更好地控制类之间的逻辑交互。接口最适合为不相关的类提供通用的功能。一个接口可以被多个类继承,在这些类中实现该接口的成员,这样接口就起到了提供统一界面的作用。
    • 接口不包含方法的实现
    • 接口不能定义字段、构造函数、常量和委托。
    • 所有接口成员默认是公有的,在接口中声明任何修饰符都是错误的。
    • 接口和抽象类的异同
    • 接口的实现:
    • 隐式实现(即实现不包含接口完整名称):接口成员必须是公共的、非静态的
    • 显式实现(即实现包含接口完整名称):不能使用任何修饰符。(如果没有充分理由,应避免显式定义接口成员)
    [/li]
  • 接口映射:接口通过类实现,对于接口声明中的每一个成员都应该对应类的一个成员,这种对应关系由接口映射来实现。
      一个接口成员确定哪一个类的成员呢?假设类C实现了接口Ia的一个接口fun,此时fun的映射过程如下: [li]①如果类C中存在一个显式成员实现,它与Ia的接口成员的fun相应,则由它来实现fun成员。
    • ②如果在类C中找不到匹配的显式接口成员实现,则看类C中是否存在一个与fun相匹配的非静态的公有成员,若有,则认为是Ia的接口成员的fun的实现。
    • ③如果以上都不满足,则在类C的基类(父类)中寻找一个基类D,用D来代替C进行重复寻找,直到找到一个满足条件的类成员实现。如果都没找到,则报告一个错误。
    [/li]
  • 看书p162-p164三个例子,接口实现的继承很容易混。
  • 上图162页第一个例子仍未搞懂
  • 接口在集合排序中的应用
      [li]Array.Sort():使用每个元素的ICompareable接口实现对整个ArrayList中元素的排序
    • Array.Sort(IComparer):使用指定的比较器。(把接口对象作为参数传递给Array.Sort())
    [/li]
  • 7
  • 8
  • 9 Windows应用程序设计
      [li]熟练掌握各个控件的属性设置和方法调用是采用C#语言设计界面友好的应用程序的基础(黑体中的两点即为主要学习内容)
    • 窗体是一个容器
    • 通过设置控件的属性可以改变其外观和标题信息(属性和外观是一体两面的东西)
    • 每个窗体对应3个文件,即两个。cs文件和一个。resx文件。前者为C#文件,后者为资源文件。
    • 窗体各事件的引发顺序
    • 焦点与Tab键次序:视图 | Tab键顺序
    • 常用的控件设计 所有控件基本属性
    • Name属性:通过此名称来引用这个控件
    • Text属性:获取用户输入或显示文本
    • Size、Location
    • Font
    • BackColor、ForeColor
    • Cursor:获取或设置 鼠标的光标
    • Visible、Enabled:Enabled决定了该控件是否被使用
    [/li]
  • 控件的外观和行为(如控件的大小、颜色、位置以及控件的使用方式等)是由它的属性决定,不同的控件拥有不同的属性,并且系统为它们提供的默认值不同。
  • 控件RichTextBox
  • 控件GroupBox分组框:用于分组(视觉上:归类;功能上:单选)
  • 控件CheckBox复选框:
      [li]属性Checked:获取或设置一个布尔值
    • MessageBox(并不是该控件,不过是书中在此介绍):其返回值DialogResult,是通过事件来返回的。
    [/li]
  • 控件RadioButton单选按钮:搭配GroupBox一起使用
  • 控件PictureBox
      作用 [li]做容器
    • 放图片
    [/li]
  • 属性Image:Image.FromFile函数加载图像(路径用绝对路径不好)
  • (问题1:如果书中没有出现这段话,怎么知道有这个方法呢?!)
  • (问题2:属性.方法 属性和方法什么关系啊?!)
  • 控件ComboBox组合框
      [li]Items的属性和方法
    [/li]
  • 控件ListBox列表框
      [li]属性SelectionMode:值MultiExtended,为允许搭配shift或ctrl键的功能
    • 事件KeyPress:在控件有焦点的情况下按下任何按键时发生
    • 例子:
    [/li]
  • 控件CheckListBox:继承自ListBox,增添了复选框功能
  • 控件Timer定时器(学会用库很重要!我原来不知道竟然想自己写一个定时器):
      [li]属性Interval:两个定时器事件之间的时间间隔
    • 其他备注:
    [/li]
  • 多个窗体之间的数据传递
      [li]通过静态字段传递数据
    • 通过构造函数传递数据(把数据放在参数中)
    [/li]
  • 创建事件过程(多个事件可以连接到单个事件过程)
      [li]在Windows窗体创建
    • 在执行时为Windows窗体创建
    [/li]
  • 10 用户界面设计
      菜单: 分类 [li]下拉式菜单:MenuStrip控件
    • 弹出式菜单(右键弹出的菜单):需要将Form的ContextMenuStip属性设置好,才能弹出
    [/li]
  • 每个菜单项都是一个ToolStripMenuItem对象,可以把菜单它理解为容器。菜单项唯一的事件就是Click事件
  • 热键设置:菜单的文字,&后加的字母 将作为该菜单项的热键
  • 通用对话框用:用ShowDialog方法显示
      [li]OpenFileDialog:打开文件:返回值为DialogResult
    • SaveFileDialog:保存文件
    • ColorDialog:选择颜色
    • FontDialog:选择字符
    • PrintDialog:打印文件
    • PrintViewDialog:打印预览
    [/li]
  • 图像列表框控件:ImageList
      [li]专门负责管理图片
    • 有几套需要管理的,就创造几个对象来管理
    • 非可视化控件
    [/li]
  • 树形视图控件:TreeView
      [li](问题:P271,方法和事件到底有什么区别,为什么分开说)
    • TreeView中的结点的组织关系是父结点 管理 子结点(管理即:添加、删除)
    • Nodes是TreeView控件的一个属性,它也是一个结点集合,每个结点就是一个Tree Node对象
    • TreeNode对象的属性和方法:P272
    [/li]
  • 列表视图控件:ListView
      [li]可包含多项,由Items集合表示,每一项就是一个ListViewItem对象,而每一个ListViewItem由其SubItems集合表示
    • ListView的Columns集合属性,由ColumnHeader对象组成
    [/li]
  • 工具栏控件(本质:图片按钮):ToolStip控件
  • 状态栏控件(和Label差不多):StatusStip
  • 11
  • 12 文件操作
      [li]输入:文件中的数据读取到内存中
    • System.IO模型提供了一个面向对象的方法来访问文件系统。以流(Stream)的方式对各种数据进行访问,这种方式不仅灵活,而且可以保证编程接口的统一。
    • (问题:体现在哪?以前没有流操作是怎样的?)
    • 文件操作的基本方式:
    • 用File类打开文件
    • 建立对应的文件流,即FileStream对象
    • 用StreamReader/StreamWriter类对文件(文本文件)流读/写 or 用BinaryReader/BinaryWriter类对文件(二进制文件)流读/写
    [/li]
  • 文件夹和文件的操作
      文件夹的操作: [li]Directory类:均为静态方法
    • DirectoryInfo类:均为非静态方法
    [/li]
  • 文件的操作:
      [li]File类:均为静态方法
    • FileInfo类:均为非静态方法
    [/li]
  • 文件流的产生-FileStream类
  • 文本文件的操作-StreamReader/StreamWriter类
  • 二进制文件的操作-BinaryReader/BinaryWriter类
  • 序列化和反序列化:将对象的公共字段、私有字段、类的名称(没有方法、事件)转换成字节流,然后写入数据流,反序列话反之。使用序列化可以将随想从一个应用程序传递给另一个应用程序。实现方法如下:
  • 内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: