深入.NET平台和C#编程
目录:
- .Net框架概述
- C#数据类型
- 集合组织
- 类的方法
- 继承和多态
- 面向对象原则和特征
- 可扩展标记语言
- 文件操作
1.概述
- 完全支持面向对象编程,提高了软件的可复用性,可扩展性,可维护性和灵活性
- 支持Web、数据库、云计算、SOA
1.1框架体系结构
.NET框架有两个主要组件:
- CRL 是.NET框架的基础,有两部分组成:① CLS 公共语言规范 ② CTS 通用类型系统
- FCL 是一个综合性的面向对象的可重用类型集合
1.2面向对象
- 类是类别 类是模子 类是对象的数据类型。
设置类的属性安全:{ get; set; } 只读;只写
定义类:类名、定义属性、定义方法。
- 万物皆对象 对象也是变量
对象使用:实例化、不同类通过"."操作、类本身可直接使用
- 方法
带参数的方法(要什么给什么)
带返回值的方法(返回的什么类型。就用什么类型变量接收)
- 封装
保障数据安全,提供清晰对外接口,类的内部可以任意修改。定义类的过程就是对事物的封装过程。
- 字段和属性
字段保存数据,不能没有字段。属性不能保存数据,字段可有可无。属性封装字段的
2.C#数据类型
- 对象数组
- 结构
结构是值类型,可以有属性和方法,不能new,结构中没构造函数,类中有默认的
访问修饰符 struct 结构名 { //结构体 }
- 构造函数
默认如果定义了一个类,系统会自动的生成一个和该类名称相同,并且没有返回值类型,甚至连Void都没有的方法,该方法就称为构造函数!
特殊的值类型:枚举和结构体。特殊的引用类型:数组和接口。
- 装箱拆箱
小转大装箱。大转小拆箱。由于装箱和拆箱过程都要损耗系统的性能,所以在开发中应该尽量避免装箱和拆箱。
- 值类型传递引用类型传递
①值类型:
每一个值类型的对象都有一个独立的内存区域保存自己的值。局部变量存放在栈中。 基本数据类型、枚举类型、结构类型
②引用类型:
要new一个一个拿出来(全部拿给的是地址)。成员变量存放在堆。 数组、类、接口
注意:值类型默认值是0,引用类型为null。
③传递:
注意:值传递和引用传递判定依据是有没有ref关键字
❶如果方法的参数类型本身就是引用类型,那么对参数值的修改会永久保存。
❷如果方法的参数类型本身是值类型,又没有ref修饰,那么对参数值的修改,不会永久保存。
❸如果方法的参数类型本身是值类型,但是有ref修饰,那么对象参数值的修改,也会永久保存。
3.集合组织
3.1集合
注意:都要设置命名空间System.Collections。
- ArrayList
Object类型 可维护的动态数组
索引0开始,可放任意类型,自动填充自动排列调整,获取元素需类型转换。
Add() 添加 可以直接使用集合初始化器{ , , }以逗号隔开
RemoveAt() 通过下标删除
Remove() 通过对象删除 一次只能移除一个
Clear() 删除所有集合
- Hashtable
ashtable 的数据是通过键(Key)和值(Value)来组织
没下标,每个元素都是一个键/值对。Add()有两个参数 一个表示键(不能重复),一个键表示所对应的值。
3.2泛型和泛型集合
注意:集合来保存数据,可以以最大限度重用代码、保护安全。提升性能 不用做类型转换 。把数据类型作为参数:泛型
- List<T>
<T>对类型进行约束,T表明集合中管理的元素类型
语法: List<T> 对象名=new List<T>(); “<T>”中的T可以对集合中的元素类型进行约束,T表明集合中管理的元素类型 示例: //建立工程师员工集合 List<SE> list=new List<SE>(); //初始化三个工程师员工 SE jack=new SE(); //属性赋值 jack.ID="001"; jack.Name="张三"; SE joe=new SE(); //赋值省略。。。 //将元素添加到集合中 list.Add(jack); list.Add(joe); 示例: //通过索引访问 SE se=list[0]; //通过索引或者对象删除 list.RemoveAt(0); list.Remove(joe); //遍历 foreach(SE sein list) { //遍历时无需类型转换 MessageBox.Show(se.SayHi()); }
- Dictionary<K,V>
可以通过K获取Value
语法: Dictionary<K,V> 对象名=new Dictionary<K,V>(); 说明:<K,V>中的K表示集合中Key的类型,V表示Value的类型 示例: //建立工程师员工集合 Dictionary<string,SE> list=new Dictionary<string,SE>(); //初始化三个工程师员工 SE jack=new SE(); //属性赋值 jack.ID="001"; jack.Name="张三"; SE joe=new SE(); //属性赋值省略 //添加元素 list.Add(jack.ID,jack); list.Add(joe.ID,ema); //打印集合中元素数目 MessageBox.Show(string.Format("部门共包括{0}个工程师。",list.Count.ToString())); //通过Key访问元素 SE se=list["001"]; //通过key删除元素 list.Remove("001"); //遍历 foreach(SE se in list.Values) { //遍历时无需类型转换 MessageBox.Show(se.SayHi()); }
- 泛型类
public Class 类名<T> 可以封装不是特定于具体数据类型的操作 支持任意数据类型
4.类的方法
- 构造函数
方法名与类名相同、没有返回值类型、通常用来初始化对象 分配字段的存储空间并给初始值
无参构造函数:缺点:对象实例化的值是固定的
带参构造函数:优点:灵活性好,通过参数来动态控制对象的特征、创建对象也可以使用对象初始化器 "{}"
注意:调用带餐函数一定要使传入的参数和参数列表相对应。C#规定:一旦有了构造函数,就不在自动分配构造函数
语法:(无参构造函数) 访问修饰符 类名() { //方法体 } 示例: public class SE { //无参构造函数:设置属性初始值 public SE() { this.ID="000"; this.Age=20; this.Name="张三"; this.Gender=Gender.male; } } 语法:(带参构造函数) 访问修饰符 类名(参数列表) { //方法体 }
- 方法重载
构造函数的重载就是:允许在同一个类中定义多个相同方法名,但参数列表(参数个数,参数类型)不同的方法
注意:要写上默认构造函数
特点:方法名相同、方法参数类型不同或参数个数不同、在同一个类中、传值要准确
优点:方法重载不仅能避免命名的麻烦,还可以使调用者不必判读方法名就可以直接使用
四步骤:了解需求、找类、找类的属性方法、实列化对象
- 对象交互
在面向对象中,对象和对象之间也存在着类似的关系("蚁巢")。
注意:不运行时没有任何交互,在事件等外力的作用下,对象和对象之间就开始相互协调工作每个类都有自己的特性和功能,我们把他封装为属性和方法 对象之间通过属性和方法进行交互,可以认为方法的参数及方法的返回值都是对象间相互传递的消息总之对象交互主要通过参数传递、方法调用及属性操作来实现
5.继承和多态
- 继承
好处:优化代码结构,让类和类产生关系。减少冗余提高复用性。为多态提供前提。
使用方法:子类继承父类,使用“”:“”冒号关键字,子类中可以访问到父类中定义的成员。
执行过程:创建子类时 先执行父类在执行子类本身的类 先会调用无参构造 可以用base指定调用父类的哪一个构造函数
遍历集合:只需要对每个对象的类型进行判断(is关键字判断是否属于给定的类型)
修饰符:强度:public>protected>private。特殊关键字:sealed,用它修饰的类是不能被继承的,称密封类
注意:一个父类也称基类可以有多个子类,一个子类也称派生类只能有一个父类。
//Emp类的构造函数 public Emp(string id,int age,stirng name,Gender gender) { this.ID=id; this.Age=age; this.Name=name; this.Gender=gender; } //SE类的构造函数 public SE(string id,stirng name,int age,Gender gender,int popularity): base(id,age,name,gender) { //继承自父类 的属性 //调用父类的构造函数可以替换掉的代码 // this.ID=id; //this.Age=age; //this.Name=name; //this.Gender=gender; //SE类的扩展属性 this.Popularity=popularity; }
- 多态
语法: 访问修饰符 virtual 返回类型 方法名() { //方法体 } 在子类中这样定义 public override string SayHi() { //方法体 }
多态是建立在继承关系之上的。同一个命令对很多人执行,根据不同的环境执行不同的行为。在继承关系的前提下,实例化出不同的对象,这些对象调用相同的方法,但却表现出不同的行为,叫多态。
多态三种:
- 虚方法
object是所有类的基类,virtual 关键字 称为虚方法,虚方法无方法体,override 关键字 称为方法的重写 (必须要有虚方法)
注意: 如果子类不重写父类的虚方法,直接执行父类的默认实现。如果子类重写了父类的虚方法,执行子类重写后的方法
- 抽象类
当我们父类中的虚方法已经虚到完全无法确定方法体的时候,就可以用抽象方法
注意:抽象类中不一定要有抽象方法,抽象方法必须存在于抽象类中。抽象方法必须被自类重写,除非子类也是抽象方法。不能实例化抽象类为对象
- 接口
接口使用 interface关键字定义,没有Class关键字,接口名一般使用"Ixxx" (i开头)。
好处:接口是一种规范和标准,约束类的行为, 接口也表示一种能力。利于代码的扩展和维护。 一个类可以实现多个接口,用逗号隔开。 一个接口可以继承多个接口,逗号隔开
注意:接口不能包含字段,但可以包含属性,不能有实现的东西,不能包含常量变量,也不能包含任何静态成员。接口、抽象类、私有的构造函数都不能实例化。接口成员不许添加访问符,默认是public。接口所有方法都是抽象方法
6.面向对原则和特征
面向对象六大原则:
①单一职责原则
②开闭原则
③里氏转换原则
子类对象可以直接赋值给父类变量,可以调用父类的成员,父类对象只能掉自己的。
④依赖倒置原则
⑤接口隔离原则
⑥迪米特原则
面向对象三大特征:
封装:保证对象自身数据的完整性和安全性。
继承:建立类之间的关系,实现代码复用,方便系统的扩展。
多态:相同的方法调用可实现不同的实现方式。
注意:is 如果正确返回true,错误返回false;as 如果成功返回对应的对象,否则返回null
7.可扩展标记语言
可扩展标记语言 标记语言。非常灵活的语言,没有固定标签,所有标签都可以自定义。通常被用于信息的记录和传递,经常被充当配置文件
特点:xml要有且只有一个根元素。大小写敏感,标签成对的,且要正确嵌套。
对象: XmlDocument 表示整个文档 XmlNode 表示一个节点 InnerText获取节点的值 Name获取节点的名字 ChildNodes 获取节点的所有子节点
Channel 各个子节点 DocumentElenment 获取根节点 Nodes获取子节点集合
//解析XML static void Main(string[] args) { //读取Xml文件方式 #region 方式一 XmlDocument doc = new XmlDocument(); //绑定文件 doc.Load("Books.xml"); //将整篇文档中的根节点玲出来 XmlNode root = doc.DocumentElement; //根据root,找所有子节点的集合 root.ChildNodes foreach (XmlNode item in root.ChildNodes) { //一个item就是一个book foreach (XmlNode child in item.ChildNodes) { //一个child代表一本书的单个属性 switch (child.Name) { case "name": Console.Write(child.InnerText); break; case "age": Console.Write(child.InnerText); break; case "sex": Console.WriteLine(child.InnerText); break; default: break; } } Console.WriteLine("================="); }
#region 方式二 XmlDocument doc = new XmlDocument(); doc.Load("student.xml"); XmlNode no = doc.DocumentElement; foreach (XmlNode item in no.ChildNodes ) { //string name=item["name"].InnerText; //string age = item["age"].InnerText; //string sex = item["sex"].InnerText; Console.WriteLine("姓名:" + item["name"].InnerText); Console.WriteLine("年龄:" + item["age"].InnerText); Console.WriteLine("性别:" + item["sex"].InnerText); Console.WriteLine("======================="); }
8.文件操作
- 五步骤:
首先需要引入 System.IO 命名空间
①创建文件流
②创建阅读或者写入器
③执行读写操作
④关闭阅读或者写入器
⑤关闭文件流
- 解决乱码问题
编程时给文件读取器对象指定对应的编码格式。Encoding 静态成员指定编码格式。Encoding.UTF8; Encoding.Default 获取操作系统的当前编码
//创建文件流 FileStream myfs=new FileStream (String filepath,FileMode fileMode); filePath 用于指定要操作的文件 fileMode 指定打开文件的模式(FileMode 枚举类型) Create:用指定的名称新建一个文件,如果文件存在,则改写旧文件 CreateNew: 新建一个文件,如果文件存在会发生异常,提示文件已经存在 Open: 打开一个文件,指定的文件必须存在 OpenOrCreate:如果文件不存在,则用指定的名称新建一个文件并打开它 Append:打开现有文件,并在文件末尾追加内容 //文件读写器 1.Stream Write写入器(用于将数据写入文件流) Stream Write.Write();用于写入流,这个流就是我们创建的文件流 Stream Write.WriteLine();用于写入一行数据,写入某些数据后跟换行符 Stream Write.close();关闭写入器 2.StreamReader 读取器 (读取流中的数据) StreamReader.ReadLine();读取文件流中的一行数据,并返回字符串 StreamReader.ReadToEnd(); 从当前位置读到末尾,返回字符串 StreamReader.close(); 关闭读取器 //文件和目录操作 File (提供文件操作) Exists(string Path) 用于检查指定文件是否存在 bool类型 Copy(string yi,string er)赋值到另外一个路径,不存在新建一个 Move(string yi,string er)将指定文件移动到一个新路径 Delete(string path) 删除指定文件,不存在也不异常 Directory(提供文件夹操作) Exists(string Path) 用于检查指定文件夹是否存在 bool类型 Move(string yi,string er)将指定文件夹移动到一个新路径 Delete(string path,bool recursive) 删除指定目录,如果recursive为true,删除子目录中的所有内容 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; namespace Wenj { public partial class Form1 : Form { public Form1() { InitializeComponent(); } //读取 private void button1_Click(object sender, EventArgs e) { FileStream fs = new FileStream("D:\\Happy.txt",FileMode.Open); byte [] bytes=new byte [1024]; int count= fs.Read(bytes,0,bytes .Length); if (bytes!=null ) { string result = Encoding.Default.GetString(bytes, 0, count); txt1.Text = result; count = fs.Read(bytes, 0, bytes.Length); } fs.Close(); } //写入 private void button2_Click(object sender, EventArgs e) { FileStream fswrite = new FileStream("D:\\Happy.txt", FileMode.Append ); string word = txt1.Text; byte[] bytes = Encoding.Default.GetBytes(word); fswrite.Write(bytes, 0, bytes.Length); MessageBox.Show("写入成功"); fswrite.Close(); } //复制 private void button3_Click(object sender, EventArgs e) { string fpath = ""; string tpath = ""; FileStream fromfs = new FileStream(fpath, FileMode.Open); FileStream tofs = new FileStream(tpath, FileMode.Create ); byte [] bytes=new byte [1024]; int count = fromfs.Read(bytes ,0,bytes .Length); //int i = 0; while (count !=0) { tofs.Write(bytes ,0,bytes .Length); count = fromfs.Read(bytes, 0, bytes.Length); MessageBox.Show("成功"); } tofs.Close(); fromfs.Close(); } private void Form1_Load(object sender, EventArgs e) { } } }