第一章 深入.NET框架
1.Microsoft.NET框架概述:
1).NET介绍
2)为什么需要.NET框架
通过如下两个问题说明为什么需要.NET框架
01,C#程序可以再不同平台(PDA,PC)的环境中运行吗?
02,使用C#程序可以调用VB.NET开发的程序吗?
答案肯定是可以的,这也足以说明.NET框架的强大之处.
3).NET框架的两个主要组件:
4).NET框架的魅力:
01.提高软件可复用,可扩展,易维护性,灵活性
02.强大的动态web支持
03.web服务
例如:天气预报服务iGoogle和支付宝网上购物商城
04.数字身份验证的支持
05.支持构建.NET程序的炫彩外衣
2..NET框架体系结构
1).NET框架体系结构
- -ADO.NET概念?
ADO.NET是软件提供的一组类库,可以帮助程序员和数据库交互,他里面有四大对象(DataReader,DataAdapter,Command,Connection)
公共语言进行时:
CLS:称为公共语言规范:
包括几种面向对象的编程语言的通用功能
.NET框架类库:
3..NET FrameWork两大组件是什么?
解析:.NET 框架类库(FCL:FrameWork Class Library)和公共语言运行时(CLR:common language Runtime)
4.CLR包含两部分:
解析:公共语言规范CLS(Common Language Specific) 通用类型系统CTS(Common Type System)
5.c#语言要编程成可以被CPU解析执行的代码需要两次编译:
第一次编译:将C#语言通过c#编译器编译成MSIL中间代码
第二次编译:将MSIL代码通过即时编译器(JIT)编译成CPU可以解析执行的代码,或者成为(平台专用代码)
6.java程序要想被CPU解析执行也是需要两次编译
一次编译:将后缀名为java的文件通过java编译器编译成后缀名为.class(字节码)文件
第二次编译:将.class文件通过java虚拟机(jvm)编译成CPU可以解析的代码
7.CLR里面至少三部分:
CTS
CLS
JIT
类库:可以看成是一个承载了N个类的容器。
类库:System.Data.SqlClient 和数据库交互
System.Data: DataSet
System.WinForms; Winform应用必须类库
System.Collections.Generic; 泛型集合
System.Net; 网络操作,下载等操作
System.IO; 文件的读写,文件夹的读写。遍历等操作
System.Drawing; 绘制图形,和验证码
类库和命名空间?
解析:一个类库一般对应一个命名空间,也可以对应多个。
第一种:将私有字段封装成公有的属性看成是封装的体现
第二种:一个类可以封装属性和方法
public class Dog
{
private string name;
public string Name
{
get{return name;}
set{name=value;}
}
public void bark()
{
}
}
面向对象编程三大特性:封装、继承和多态
访问修饰符:
public:任何位置,包括跨程序集。
internal:在当前程序集(项目)中都可以访问
private:只能在当前类中访问(当前类的花括号中访问。)
protected:只能在当前类和其子类中使用
变量,类和方法的命名法
骆驼命名法(camel):第一个单词的首字母小写,后续有含义的单词首字母大写。 变量
帕斯卡命名卡(pascal):每一个单词的首字母都大写。类名和方法名
new:代表含义:
Student stu=new Student();
01.创建对象
02.开辟空间
03.自动调用构造函数
字段和属性区别?
解析:01.属性不能保存数据,真正保存数据的是字段
02.属性是可有可无的,字段是必须的。
03.如果字段只想让类内部访问,那么设置成private,如果想找一个中间者,
在Main方法中访问到Student类中的私有字段,那么属性可以是一种选择。
希望:推荐大家以后书写类的时候,字段和属性成对出现。
.属性无非就是有get和set两个访问器组成
get:取值
set:赋值
自动属性
自动属性应用场景:当我们不需要做逻辑判定的时候可以使用自动属性
定义自动属性在后台会自动帮我们生成一个对应数据类型的私有字段
第二章 深入C#数据类型
封装
. 封装又称信息隐藏,是指利用抽象数据类型(自定义类UserInfo)将数据和数据的操作结合在一起,使其构成一个不可分割的独立实体,尽可能的隐藏内部的细节,只保留一些对外接口,使之于外部发生联系。
体现一:把方法和属性封装到类中,看成是一种封装
体现二:将私有字段封装成 公有的属性
封装的优点
第一:code重用;
第二:不必关心具体的实现; (方法)
第三:面向对象三大特征之一;
第四,具有安全性!
关于数组的那些事儿
如果我们定义一个数组,并且赋值了
int[] nums={1,2};
nums当中保存 的是堆中的地址:例如:0x001
nums[0]:访问的是堆中的内容
.结构体
*01.结构体不用new,就可以直接对其属性赋值
*02.结构体中可以有字段,属性和方法
*03.结构体是值类型,类是引用类型
*04.在结构体中不能给字段赋初值,但是类中可以.
*05.结构体中没有默认构造函数,但类中有默认构造函数
构造函数
默认如果定义了一个类,系统会自动的生成一个和该类名称相同,并且没有返回值类型,甚至连Void都没有的方法,该方法就称为构造函数
注意问题:值类型的直接父类都是ValueType,而ValueType又继承自Object
特殊的值类型:枚举和结构体
特殊的引用类型:数组和接口
装箱和拆箱
由于装箱和拆箱对系统性能损耗很大,所以在真实的开发中我们尽量避免装箱和拆箱的操作
Object:是引用类型,并且是所有数据类型(值类型,引用类型)的父类
什么时候应该装箱,什么时候应该拆箱?
解析:由于装箱和拆箱过程都要损耗系统的性能,所以在开发中应该尽量避免装箱和拆箱。
值类型传递和引用类型传递
01.如果方法的参数类型本身就是引用类型,那么对参数值的修改会永久保存
例如:public void TP(SE se)
{
se.Count++;//真正的修改se对象的Count值
}
02.如果方法的参数类型本身是值类型,又没有ref修饰,那么对参数值的修改,不会永久保存()
03.如果方法的参数类型本身是值类型,但是有ref修饰,那么对象参数值的修改,也会永久保存。
第三章 使用集合组织相关数据
集合概念
集合:某些指定的对象(SE)集中在一起就是集合
数组:可以存储相同数据类型的一堆数据的容器
集合
集合分为泛型集合和非泛型集合
泛型集合分为单列和双列集合 (List<T>和Dictionary<K,V>)
非泛型集合分为单列和双列集合 (ArrayList和HashTable)
常用的方法和属性
Add(); //添加 Remove(); //删除 RemobeAt(); //根据索引删除 不适用 双列集合 count //集合存储元素的个数 Contains(); //检测元素是否存在 ContainsKey(); // ContainsValue(); Capcity //集合占用空间
注意事项:如果删除了集合中的某一个元素,那么集合的索引会自动维护
遍历方案:
ArrayList list=new ArrayLIst(); Student stu1=new Student(); stu1.Name="jiejie"; stu1.Age=15; list.Add(stu1); Student stu2=new Student(); stu2.Name="jiji"; stu2.Age=18; list.Add(stu2); //foreach foreach(Student item in list) { Console.WriteLine(item.Age+"\t"+item.Name); } //for for(int i=0;i<list.Count;i++) { Console.WriteLine((Student)list[i].Name); }
HashTable 遍历三种方案 HashTable table=new HashTable(); 第一种方式:遍历所有的Keys foreach(var item in table.Keys) { //一个item代表一个key Console.WriteLine("key是{0}\tvalue是{1}",item,table[item]); } 第二种遍历方式:遍历所有的value集合 foreach(var item in table.Values) { //一个item代表一个value Console.WriteLine("value是{0}",item); } //遍历整个table foreach(DictionaryEntry item in table) { Console.WriteLine("key是{0}\tvalue是{1}",item.Key,item.Value); }
第四章 深入类的方法
(1)构造函数
方法名和类名相同,没有返回值
注意:在C#中,当我们定义了一个类后,系统底层默认会生成一个和类名相同的无参构造,但是如果我们定义了一个带参构造,系统将不生成无参构造,但是在
真正的开发中建议大家定义两个构造函数,一个无参构造和带参构造
public class SE { public SE() { } public SE(string id,string name,int age,Gender gender,int popularity) { Id=id; Name=name; Age=age; Gender=gender; Popularity=popularity; } }
(2)方法的重载
在同一个类中,如果有多个方法方法名相同,但是参数的个数,顺序,类型不同的多个方法可以构成重载和方法的返回值类型没有关系。
public void Say(string name,int age) { } public void Say(int age,string name) { }
(3)对象间的交互
//遥控器类 public class RemoteControl { //开机 public void TurnOn(Tv tv) { tv.Open(); //调用电视机对象的开机方法 } //关机 public void TurnOff(Tv tv) { tv.TrunOff(); } //换台 public void ChangeChannel(Tv tv) { Console.WriteLine("请输入频道:"); string ChannelNo=Console.ReadLine(); tv.Change(ChannelNo); } //电视机类 public class Tv { public boolean isOn=false; //是否开机 //打开电视机 public void Open() { if(isOn) { Console.WriteLine("电视机已打开"); } else { Console.WriteLine("成功打开电视机"); isOm=true; } } //关机 public void TurnOff() { if(isOn) { Console.WrteLine("电视机正在关机"); isOn=false; } else { Console.WriteLine("电视机已关闭"); } } //换台 public void Change(string channelNo) { if(isOn) { Console.WriteLine("正在切到{0}台",channelNo); } } //测试Main()方法 static void Main(String[] args) { RemoteControl controler=new RemoteControl(); Tv tv=new Tv(); //开机 controler.TurnOn(tv); //切换频道 controler.ChangChannel(tv); //关机 controler.TurnOff(tv); Console.ReadLine(); }
看到这里你明白了一点了没有,回想一下上面所写的,这是一个重复的事情,一遍不行就两遍,再教你个小方法,没事的时候你就想想你学了点什么,看看自己还记得多少,忘记的就去看看自己写的,好了接下来继续吧!
第六章 初识继承和多态
(1)
继承的概念是什么呢?就是一个类可以继承另一个类的属性和方法(成员)
继承是面向对象编程中的一个非常重要的特性。
好了,废话不多说,下面切入正题:
1.首先我们定义一个子类,给它创建两个构造:一个无参构造和一个有参构造
定义一个枚举类
在定义的子类中它有自己独有的属性:
在定义的父类中的属性和构造:
在Main方法中:
同时要注意,在调用子类的带参构造时,我们要想到调用子类构造的时候,没有使用base关键字调用父类的指定的构造,默认调用父类的无参构造.
补充一下:
01.base代表父类对象,如果base():调用父类的构造函数
02.base代表的是方法调用,是不需要参数类型的
03.base(传参顺序和父类构造一致,变量名和子类构造参数一致)
(2)在这里补充一点访问修饰符
我们所知道的:public private protected
下面我画一个图来简单的描述一下(√表示可以,×表示不可以)
当前类 子类 其他类(Program)
private √ × ×
protected √ √ ×
public √ √ √
总结:我们可以清晰的明白三种访问修饰符对类成员的访问限制强度:private>protected>public
(3)new 子类底层原理图
我简单的用一个图来描述一下:
用文字描述:
1.走到子类构造,不进入构造体
2.转向父类,进入父类构造体执行
3.转回子类构造,执行子类构造体
4.转到Main,内存中构建出子类对象
(4)继承还具有两大特性这个我们也不要忘记了,就是单根性和传递性
单根性指的就是一个子类只有一个父类
传递性就是只要跟父类有继承关系,就可以使用父类的属性和方法
(5)接下来我们讲一讲多态
1.多态是什么呢?字面上的意思就是多种形态
用专业一点的话来说就是指同一个操作作用于不同的对象时,可以有不同的解释,产生不同的执行效果。
我们所接触的方法重载也是多态的一种方式。
如何实现多态呢?不要急下面我来解说
(6)实现方法的重写
在父类中定义的方法,用virtual关键字来定义为虚方法
在子类中定义自己的方法,用override关键字来修饰,实现对父类的方法的重写
(7)定义父类变量,用子类变量初始化父类变量
下面来一个小案例:
//创建一个Person父类 public class Person { public virtual void SayHello() { //父类特有的方法 Console.WriteLine("父类打招呼方法"); } } //创建一个Korea子类 public class Korea:Person //在这里要注意它继承于Person类 { public override void SayHello() { Console.WriteLine("金喜善打招呼方法"); } } //创建一个Chinese类 public class Chinese:Person //在这里要注意它继承于Person类 { public override void SayHello() { Console.WriteLine("你好!"); } } //创建一个American类 public class American:Person //在这里要注意它继承于Person类 { public override void SayHello() { Console.WriteLine("Hello"); } } 前面我们也学过泛型了下面我们就用泛型来存储 List<Person> list=new List<Person>(); Chinese chinese=new Chinese(); American usa=new American(); Korea korea=new Korea(); list.Add(chinese); list.Add(usa); list.Add(korea);
下面我们可以用foreach来遍历
方式一: foreach (Person person in list) { person.SayHello(); } 方式二: foreach (Person person in list) { //方式二:不使用统一调用 if (person is Chinese) { Chinese chinese= person as Chinese; chinese.SayHello(); } if (person is Korea) { Korea chinese= person as Korea; korea.SayHello(); } if (person is American) { American chinese= person as American; american.SayHello(); } }
下面我再穿插个示例:
在Main方法中调用
看过我文章的人应该知道,在这里我们又回顾了一下,你记住了吗?
第七章 深入理解多态
(1)里氏替换
定义:在一个软件系统中,如果子类替换父类出现的位置,而对整个软件系统功能没有影响
//交通工具类 public class TrafficTool { public vartual void Run() { Console.WriteLine("车在行驶"); } } //地铁类 public class Tube:TrafficTool { public voerride void Run() { Console.WriteLine("地铁在行驶中"); } } //小汽车类 public class Car:TrafficTool { public voerride void Run() { Console.WriteLine("小汽车在行驶中"); } } //自行车类 public class Bicycle:TrafficTool { public override void Run() { Console.WriteLine("自行车在行驶中"); } } //给Employee类添加GoHome()方法:搭乘交通工具回家 public class Employee { //以父类类型作为参数 public void GoHome(TrafficTool tool) { Console.WriteLine("员工"+Name); tool.Run(); } } //测试Main()方法 static void Main(String[] args) { SE ai=new SE("123","艾边成",25,Gender.male,100); SE joe=new SE("103","Joe",30,Gender.female,200); //实例化PM对象 PM pm=new PM("890","盖茨",50,Gender.female,30); //定义员工集合 List<Employee> list=new List<Employee>(); list.Add(ai); list.Add(joe); list.Add(pm); //员工选择不同的交通工具回家:传递实际创建的子类对象 list[0].GoHome(new Bicycle()); list[1].GoHome(new Car()); list[2].GoHome(new Tube()); Console.ReadLine(); }
(2)抽象类和抽象方法
定义:抽象方法是一个没有实现的方法,通过定义方法时增加的关键字abstract可以声明抽象方法
语法:
访问修饰符 abstract 返回类型 方法名();
注意:抽象方法没有闭合的大括号,而是直接跟了一个分号;,也就是说它没有方法体。
含有抽象方法的类必然是抽象类
语法:
访问修饰符 abstract class 类名{}
简单示例: public abstract class TrafficTool { public abstract void Run(); }
/// <summary> /// 父类 工作类 /// </summary> public abstract class Job { //抽象方法 public abstract void Show(); //工作类型 public string Type { get; set; } //工作名称 public string Name { get; set; } //工作描述 public string Describe { get; set; } //无参构造 public Job() { } //带参构造 public Job(string type,string name,string des) { this.Type = type; this.Name = name; this.Describe = des; } }
public class Tests : Job { /// <summary> /// 子类 测试类 /// </summary> //测试类的方法 public override void Show() { FrmTests tt = new FrmTests(); tt.Show(); this.Num = Num; this.BugNum = BugNum; this.Time = Time; } //个数 public int Num { get; set; } //bug数 public int BugNum { get; set; } //时间 public string Time { get; set; } //无参构造 public Tests() { } //带参构造 public Tests(string type,string name,string des):base(type,name,des) { } }
总结:
1.一个类用abstract修饰,就是抽象类
2.抽象类不能实例化
3.抽象方法不能有方法体连{}不能有
4.抽象方法只能在抽象类中
5.抽象方法存在的目的就是为了约束类中方法存在的形式(返回值类型和参数列表)
6.抽象类不能是静态类和密封类
7.抽象类中所有的抽象方法必须被子类重写,除非子类本身也是抽象类
8.一键重写所有抽象方法的快捷键 Ctrl+.(无输入法情况下) Shift+Alt+F10
第九章 文件操作
(1)文件的读写
这是一个简单的窗体读写功能
private void btn01_Click(object sender, EventArgs e) { string path = txt01.Text;///路径地址 string content = txt02.Text;//保存的文本 if(path.Equals(null)|| path.Equals("")) { MessageBox.Show("文件地址不能为空"); return; } try { FileStream stream = new FileStream(path,FileMode.Create); StreamWriter writer = new StreamWriter(stream); writer.Write(content); writer.Close();//后开的先关 stream.Close(); MessageBox.Show("写入成功"); } catch (Exception ex) { MessageBox.Show(ex.Message); throw; } }
private void btn02_Click(object sender, EventArgs e) { string path = txt01.Text; if(path.Equals(null)||path.Equals("")) { MessageBox.Show("文件地址不能为空"); return; } try { FileStream stream = new FileStream(path, FileMode.Open); StreamReader reader = new StreamReader(stream); string content = reader.ReadLine(); txt02.Text = content; reader.Close(); stream.Close(); } catch (Exception ex) { MessageBox.Show(ex.Message); throw; } }
(2)文件和目录的操作
/// <summary> /// 文件类 /// </summary> public class MyFile { //文件长度 public float Length { get; set; } //文件名称 public string Name { get; set; } //文件路径 public string Path { get; set; } //文件类型 public string Type { get; set; } }
private void FrmMain_Load(object sender, EventArgs e) { TreeNode tn = new TreeNode("C:\\"); tn.Tag = "C:\\"; tvList.Nodes.Add(tn); tn = new TreeNode("D:\\"); tn.Tag = "D:\\"; tvList.Nodes.Add(tn); tn = new TreeNode("E:\\"); tn.Tag = "E:\\"; tvList.Nodes.Add(tn); } //绑定treeview的方法 private void BindInfo(TreeNode node) { try { //清空选中文本的节点集合 tvList.SelectedNode.Nodes.Clear(); //初始化一个directory对象 DirectoryInfo dir = new DirectoryInfo(node.Tag.ToString()); //返回当前目录的子目录 DirectoryInfo[] info = dir.GetDirectories(); foreach (DirectoryInfo item in info) { //一个item代表一个子节点 TreeNode tn = new TreeNode(); tn.Text = item.Name; tn.Tag = item.FullName; node.Nodes.Add(tn); } //清空ListView的数据 lvList.Items.Clear(); //FileInfo 初始化 FileInfo 类的新实例,它作为文件路径的包装。 //GetFiles() 返回当前目录的文件列表 FileInfo[] files = dir.GetFiles(); foreach (FileInfo file in files) { //把数据绑定到ListView ListViewItem item = new ListViewItem(file.Name);//文件名称 item.SubItems.Add((file.Length / 1024).ToString()); //文件大小 item.SubItems.Add(file.Extension);//文件类型 item.SubItems.Add(file.FullName);//文件路径 lvList.Items.Add(item); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void tvList_AfterSelect(object sender, TreeViewEventArgs e) { //选中的节点的文本值传到BindInfo()方法中 TreeNode tn = tvList.SelectedNode; BindInfo(tn); } private void lvList_DoubleClick(object sender, EventArgs e) { //双击打开选中的文件 string path = lvList.SelectedItems[0].SubItems[3].Text; Process.Start(path); } private void 复制ToolStripMenuItem_Click(object sender, EventArgs e) { //提示用户选择文件夹。 FolderBrowserDialog fold = new FolderBrowserDialog(); DialogResult result = fold.ShowDialog(); //选中的路径 string path = lvList.SelectedItems[0].SubItems[3].Text; //声明一个新路径 赋值为null string paths = null; //当点击确定的时候复制新的路径 if (result == DialogResult.OK) { paths = fold.SelectedPath; paths += "\\" + lvList.SelectedItems[0].SubItems[0].Text; File.Copy(path, paths); MessageBox.Show("复制成功"); } } private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) { //选中要删除的文件的路径 File.Delete(lvList.SelectedItems[0].SubItems[3].Text); BindInfo(tvList.SelectedNode); MessageBox.Show("删除成功"); }
(3)
小练习:
private void btnRead_Click(object sender, EventArgs e) { string path = "E:\\Hi.txt"; FileStream fs = new FileStream(path,FileMode.Create); byte[] bt = new byte[1024]; int count = fs.Read(bt,0,bt.Length); string result = Encoding.Default.GetString(bt,0,count); txt1.Text = result; } private void button1_Click(object sender, EventArgs e) { string fromPath = "D:\\ISO\\cn_windows_7_ultimate_with_sp1_x86_dvd_u_677486.iso"; string ToPath = "E:\\18岁以下禁止观看.iso"; FileStream fromFs = new FileStream(fromPath, FileMode.Open); FileStream toFs = new FileStream(ToPath, FileMode.Create); byte[] bytes = new byte[1048576]; int count = fromFs.Read(bytes, 0, bytes.Length); int i = 0; while (count != 0) { toFs.Write(bytes, 0, count); count = fromFs.Read(bytes, 0, bytes.Length); txt1.Text=i.ToString(); i++; } toFs.Close(); fromFs.Close(); MessageBox.Show("Copy Success!"); }