第一章 .Net入门
//VS快捷键
//Ctrl+Shift+L 删除整行
// Ctrl+K+D 格式化
// Ctrl+L 智能提示
ctrl+W+L 在vs里显示数据库连接
//解决方案 与 项目 区别
//生成解决方案 与 重新生成解决方案
//Debug 调试模式:输出调试信息
//Release 发型模式:不输出调试信息
//反编译器 ILSpy
Console.Title = "第一章基础"; Console.BackgroundColor = ConsoleColor.Red;//背景色 Console.ForegroundColor = ConsoleColor.Blue;//前景色 Console.Beep(); Console.WriteLine("你好"); Console.ResetColor(); Console.ReadKey(); Console.Clear(); Console.WriteLine("222222"); string s = Console.ReadLine(); Console.WriteLine("您刚才输入了:" + s); Console.SetCursorPosition(5, 5);//设置光标位置,xy有限制不能超过最大长度 int i = 10; Console.WriteLine(i++); Console.ReadKey();
C# winform应用程序运行后,bin文件夹中会自动生成3个文件和一个应用程序 其中的: "*..pdb", "*.vshost.exe", "*..vshost.exe.manifest" 的作用是什么? *.vshost.exe 宿主进程,帮助程序调试的. *.Manifest 是Build解决方案的时候产生的, PDB(程序数据库)文件保持着调试和项目状态信息,从而可以对程序的调试配置进行增量链接。 vshost.exe 是宿主进程文件。宿主进程是 Visual Studio 2005 中的一项功能,能提高调试性能,支持部分信任调试并支持设计时表达式计算。宿主进程文件的文件名中包含 vshost,并位于项目的输出文件夹中。 作用: 宿主进程创建一个应用程序域并将调试器与应用程序关联起来。执行这些任务会导致在开始调试和开始运行应用程序之间有很明显的延迟。通过在后台创建应用程序域和关联调试器,并在运行应用程序之间保存应用程序域和调试器状态,宿主进程使性能得到提高。部分信任调试及设计时表达式计算(即时窗口)。部分信任在安全页中配置 vshost.exe.manifest: Windows XP通过XML文件来实现这一功能,这些XML文件保存了有关应用程序配置的元数据,这里所说的XML文件,就是Manifest清单文件。 Manifest事实上就是一个以.manifest为后缀的XML文件,用于组织和描述隔离应用程序及并行组件,其内部的信息如元素则标识着一个唯一的程序集,和其他信息一起,他们用于COM类、接口及库的绑定和激活,而这些信息,以往都是存储在注册表中的。另外,Manifests也制定了组成程序集的文件及Windows类。
第二章 C#语言基础
变量 命名 驼峰命名法 首字母大写 第一个字母小写 openComputer
类,方法 命名 首字母大写 OpenComputer
数值类型简介和显式隐式转换
//小范围向大范围转换,可以用隐士转换. //隐士转换 byte bb = 4; int cc = bb; //显示转换 int i = 3; byte b = (byte)i;//每超出256会重新计算,如果i=256 ,b=0 Convert.ToByte(i);//如果i>255就会报错!
小数数据类型
//double>float double d1=3.14D; //ok,3.14d也可以 double d2=3.14; //ok,一般不用写D double d3=3; //ok float f1=3.14; //error 不能从double转换到float,小数默认是double float f2=3.14F; //ok ,3.14f 也可以 double d4=3.14f; //ok,因为double>float,小范围向大范围转换,可以进行隐士转换
int i9 = 5 / 8; ////=0 int 进行运算结果还是 int Console.WriteLine(5/8);//=0 ,int 进行运算结果还是 int Console.WriteLine(5.0 /8.0);//=0.625 Console.WriteLine(5.0/ 8);//=0.625 double和int结果是double Console.WriteLine(5 / 8.0);//=0.625 Console.WriteLine(5 / 8F);//=0.625 int和float结果是float Console.WriteLine(5F / 8F);//=0.625
//小数在计算机中 二进制存储;近似存储 long phoneNum = 13888888888;//不能用int 超了边界 double d = phoneNum/80d;//173611111.1 int zhengshubufen = (int)d;//173611111 double xiaoshubufen = d - zhengshubufen;//输出0.099999994039535522 Console.WriteLine(xiaoshubufen); double d1 = 1.1;//173611111.1 int i = 1;//173611111 Console.WriteLine(d1-i);//输出0.1 Console.ReadKey();
字符串,转义符
string s = @"C:Program Files (x86)"; string s1 = "C:\Program Files (x86)"; string s2 = "你"好";
char 有且只有一个字符.一个char占用2个字节
char ch1='a';
数据类型转换
object i=null; string s1 = Convert.ToString(i);//如果i=null 这种不会抛异常 string s2 = i.ToString();//如果i=null 这种会抛异常 string s3 = "123"; int ii = Convert.ToInt32(s3); long l = Convert.ToInt64(s3); double d = Convert.ToDouble(s3);
枚举
//枚举 class Program { static void Main(string[] args) { { //枚举 enum Dir d = Dir.East; Console.ReadKey(); } } } enum Dir { East, West, South, North }
基本运算符
//基本运算符 int i1 = 22 % 5;//求余数 int i2 = 5; i2++;//先赋值,再自增 ++i2;//先自增,再赋值 i2--; Console.WriteLine("nihao"+5+5);//nihao55 Console.WriteLine("nihao" + (5 + 5));//nihao10 Console.WriteLine(5+4 + "nihao");//9nihao int i3 = 5; i3+= 3;//i3=i3+3; i3 -= 3;//i3=i3-3; i3 *= 3; i3 /= 3; Int32.TryParse("s",out i1);//防止输入的是字符串,可以尝试这种转换, 相当于 try Console.WriteLine(i3);
值类型的赋值
//值类型的赋值 //int i = 10; //int j = i;//复制传递.让j指向i"当前" 所指向的内存 //变量交换 int i = 10; int j = 20; j = i + j; i = j - i; j = j - i; Console.WriteLine("i=" + i + "j=" + j); Console.ReadKey();
赋值运算本身也是一个值
int a = 4; int b = 5; Console.WriteLine(a=b);//输出5 int i=10; Console.WriteLine(i++);//输出10,i++, 先赋值再自增 Console.WriteLine(++i);//输出11,i++, 先自增再赋值 Console.ReadKey();
逻辑运算符的短路问题
int i = 8; bool b = (i > 10) && ((i = i + 5) > 10); Console.WriteLine(b);//false Console.WriteLine(i);//输出8 ,因为前面i>10已经为false,所以后面比较未执行 Console.ReadKey();
三元运算符
int i =Convert.ToInt32( Console.ReadLine()) ; Console.WriteLine(i % 2==0? "偶数" : "奇数"); Console.ReadKey();
switch
int i = 5; switch(i)//也可以i+5 { case 3: case 4: case 5: Console.WriteLine("春天"); break; case 6: case 7: case 8: Console.WriteLine("夏天"); break; case 9: case 10: case 11: Console.WriteLine("秋天"); break; case 12: case 1: case 2: Console.WriteLine("冬天"); break; default: Console.WriteLine("非法"); break; } Console.ReadKey();
第三章 C#语言基础2
break 终止循环
continue终止本次循环
数组
//数组声明,使用 //对于 int,double,float等数组,没有赋值的元素被初始化为0;对于string等引用类型,初始化为null //不能动态增加数组的大小,要用List int [] a1=new int [5]; a1[0] = 1; Console.WriteLine(a1[0]);//输出1 Console.WriteLine(a1[1]);//输出0 Console.WriteLine(a1[2]);//输出0 int[] a2 = { 3,5,2}; Console.WriteLine(a2[2]);//输出2 Console.ReadKey();
字符串数组
string strPhoneNum = txtPhone.Text.Trim(); char ch = strPhoneNum[0]; if (ch != '1') { MessageBox.Show("手机号第一位不是1,你的是中国手机号吗?!"); return; } for (int i = 0; i < strPhoneNum.Length; i++) { char ch2 = strPhoneNum[i]; if(!char.IsDigit(ch2))//char.IsDigit 指示指定的 Unicode 字符是否属于十进制数字类别 { MessageBox.Show("手机号中怎么还有非数字?不要邮箱哦!"); return; } }
方法
static void Main(string[] args) { { int[] num = { 3, 5, 7 }; Console.WriteLine(Sum(num));//15 Console.WriteLine(Sum(3, 4, 5));//12 //会把第一个参数算第一个,其他算params Test("1", "2", "3");//输出我1我 2 3 Console.ReadKey(); } } /// <summary> /// 方法 参数,返回值,重载 ,可变长度数组params /// </summary> /// <param name="nums"></param> /// <returns></returns> static int Sum(params int[] nums) { int sum = 0; for (int i = 0; i < nums.Length; i++) { sum = sum + nums[i]; } return sum; } static void Test(string s, params string[] strs) { Console.WriteLine("我" + s + "我"); for (int i = 0; i < strs.Length; i++) { Console.WriteLine(strs[i]); } }
真随机数
递归
static void Main(string[] args) { lala(1); } static void lala(int i) { Console.WriteLine("递归了"); if(i<5) { lala(++i);//先运算再赋值,千万不能用i++死循环,因为是先赋值再运算 } }
斐波那契额数列
//斐波那契额数列 static void Main(string[] args) { Console.WriteLine(fib(5)); Console.ReadKey(); } //1,1,2,3,5,8,13,21.....第n位(从0开始)值是多少?斐波那契额数列 //递推方法:f(n)=f(n-1)+f(n-2)。终止条件:n=0,1 return 1。 static int fib(int n) { if (n < 0) { throw new Exception("n不能是负数"); } if (n == 0 || n == 1) { return 1; } return fib(n - 1) + fib(n - 2); }
第四章 C#面向对象基础
对象的引用传递
static void Main(string[] args) { //类对象是引用传递 //new 才会产生新的对象 Person yzk = new Person(); yzk.SetAge(18); yzk.SetName("嗷嗷嗷"); yzk.SayHello(); //“Person weiren = yzk;”weiren指向yzk当前所指向的对象。 Person weiren = yzk; weiren.SetAge(30); weiren.SetName("金正恩"); weiren.SayHello(); yzk.SayHello(); Person p = new Person(); p.SetAge(30); p.SetName("哈哈"); Test(p); p.SayHello(); Console.ReadKey(); } //把一个对象传递进方法中,传递的也是同一份引用 static void Test(Person p) { p.SetAge(p.GetAge() + 5); } class Person { string name; int age; public void SayHello() { Console.WriteLine("我是" + this.name + ",今年" + this.age + "岁"); } public void SetAge(int age) { this.age = age; } public void SetName(string name) { this.name = name; } public int GetAge() { return this.age; } }
值类型(int,long,double,float,boolean,枚举,结构体等)是复制传递,不能为null.
局部变量必须初始化,成员变量声明时默认初始化,基本数值类型默认初始化为int,String等非基本类型初始化为null
属性
private string phone; public string Phone { get { return phone; } set { phone = value; } } public string Card { get; set; }
class Person { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public Person() { } public Person(int id) { this.Id = id; } } Person p = new Person() { Id=5,Name="abc"}; Person p1 = new Person(5) { Name = "aaa", Age = 5 }; Person p2 = new Person { Id=5,Name="a"};
static
静态类第一次用到这个类的时候,才会初始化。如果你的程序完全没有用到这个类,那么也不会初始化
static void Main(string[] args) { Person.aaa(); Console.ReadKey(); } class Person { /* 1、一些场景下会要求一个类的多个实例共享一个成员变量;有时候想定义一些不和具体对象关联、不需要new就调用的方法 举例:Console类的WriteLine,MessageBox的Show 2、static方法不需要new就可以直接通过类名调用。 3、static变量不需要new就可以直接通过类名调用。static变量是共享的内存空间,非static变量则是对象隔离的。 4、static 方法中无法使用this关键字,因为static独立于对象存在,不是任何人的唯一。 5、static成员中只能访问static成员,不能直接访问非static成员。非static成员可以访问static成员。*/ public static int g_i;//相当于全局变量 public static string aaa() { //不能用this return "aaa;"; } }
单例模式
//1、有的类在系统中只能有一个对象(*,资源管理器、缓存管理器等),这时就要使用“单例模式”(singleton)。实现单例模式有很多方法,先介绍最简单、最实用的“饿汉式”。 //2、单例模式的实现步骤: //1)构造函数声明为private,这样避免外界访问 //2)定义一个private readonly static的对象实例,static成员的初始化只在类第一次使用的时候执行一次。readonly修饰变量只能在构造函数或者初始化的时候赋值。 //3)定义一个public static的getInstance方法,返回唯一实例。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SingletonTest1 { class God { //静态变量的初始化只执行一次 private static God Instance = new God(); private God() { }//构造函数声明为private,避免外界调用 public void ZhaoYaoDaDi() { Console.WriteLine("照耀"); } public static God GetInstance() { return Instance; } } }
静态代码块
class MyTest { static MyTest() { Console.WriteLine("zi 静态代码块"); } public MyTest() { Console.WriteLine("zi 构造方法"); } } MyTest t1 = new MyTest(); MyTest t2 = new MyTest(); //静态代码块在类第一次被使用的时候执行一次,在构造函数执行之前执行。且只执行一次。 public class MyJingTaiDaimaKuai { public static int i = test1();//最开始执行 public int age = test2();//new的时候先执行成员变量的初始化,再执行构造函数 static MyJingTaiDaimaKuai() { Console.WriteLine("静态代码块");//再执行 } public MyJingTaiDaimaKuai() { Console.WriteLine("构造函数"); } public static int test1() { Console.WriteLine("test1"); return 3; } public static int test2() { Console.WriteLine("test2"); return 333; } } MyJingTaiDaimaKuai a1 = new MyJingTaiDaimaKuai(); Console.WriteLine(a1.age); MyJingTaiDaimaKuai a2 = new MyJingTaiDaimaKuai(); Console.WriteLine(a2.age); //一般用于对类进行初始化,以后会用 //只要一旦开始“接触一个类”,静态成员、static代码块就会被执行
继承中的构造函数
//C#中一个类可以“继承”自其他类,如果A继承自B,则A叫做B的子类,B叫做A的父类(基类)。子类会从父类继承所有非private成员。子类还可以有子类。 //C#中一个类只能有一个父类,如果没指定父类,则System.Object为父类。 //子类的构造方法默认都去访问了父类的无参构造方法:在子类中的构造方法后都有一行默认语句 base() class Fu { public Fu() { Console.WriteLine("fu"); } } class Zi : Fu { public Zi() : base()//不管是否显式调用,控制台都会输出fu { Console.WriteLine("zi"); } } Zi z = new Zi(); //先执行父类的构造函数把父类初始化完成,再初始化子类的。 //可以通过base(参数)去访问父类中的有参构造函数。可以通过this(参数...)去访问本类中的其他构造函数。 class Fu { public Fu(int a) { Console.WriteLine("fu"+a); } } class Zi : Fu { public Zi():base(0) { Console.WriteLine("zi"); } public Zi(int a):base(a) { Console.WriteLine("zi"+a); } } //如果定义了构造函数,则类就不会有默认的无参构造函数;如果父类中没有默认的,则子类构造函数必须显示调用父类的构造函数
private成员无法被子类访问,子类只能通过父类的非private方法“间接”访问父类的private成员。这样保证了父类private成员的安全性。
protected成员只能被自己以及子类(直接或者间接)访问,无法被“外姓人”访问。
面向对象三大特征:封装、继承、多态。多态是面向对象最强大的一个特征,也是最难的一个特征,设计模式等都是多态的体现。大型项目架构也大量应用多态。
子类中定义和父类中一样的方法就叫“重写(Override)或覆盖”,父类中可以被Override方法要声明为virtual 。Override和OverLoad区别见备注
class DiQiuRen { public virtual void speak(){Console.WriteLine("我是地球人");} } class Chinese : DiQiuRen { public override void speak(){Console.WriteLine("我是中国人");} public void baiNian(){Console.WriteLine("过年好!");} } DiQiuRen dqr1 = new DiQiuRen(); dqr1.speak(); Chinese zgr1 = new Chinese(); zgr1.speak();
多态精髓
static void Main(string[] args) { //父类变量可以指向子类对象,内存中也还是子类对象,有且只有这么一个对象.变量是什么类型没关系,到底执行谁的方法只要取决于内存中的对象是什么类型 //能够调用什么方法由变量类型决定,执行谁的方法由实际指向的对象决定. DiQiuRen di = new ZhongGuoRen(); // ZhongGuoRen z = new DiQiuRen();这种不对 di.Speak();//输出我是中国人 Console.ReadKey(); } class DiQiuRen { public virtual void Speak() { Console.WriteLine("我是地球人"); } } class ZhongGuoRen : DiQiuRen { public override void Speak() { Console.WriteLine("我是中国人"); } }
多态与类型转换
static void Main(string[] args) { DiQiuRen dqr1 = new DiQiuRen(); DiQiuRen dqr2 = new ZhongGuoRen(); ZhongGuoRen zgr1 = new ZhongGuoRen(); DiQiuRen d3 = zgr1; d3.Speak();//输出我是中国人 //ZhongGuoRen zgr2 = d2;//错误,跟int i=5; byte b=i;一样....编译器只看类型,无法看实际是什么 ZhongGuoRen zgr2 = (ZhongGuoRen)dqr2;//不同类型的可以通过显示转换. ZhongGuoRen zgr3 = (ZhongGuoRen)dqr1;//抛异常.如果对象就是父类对象,当被看成子类对象的时候会失败 Console.ReadKey(); } class DiQiuRen { public virtual void Speak() { Console.WriteLine("我是地球人"); } } class ZhongGuoRen : DiQiuRen { public override void Speak() { Console.WriteLine("我是中国人"); } }
抽象类
//把类标记为abstract,这样的类无法被直接实例化(new),这就叫抽象类。 //抽象方法没有方法体;一旦类中定义了抽象方法,类必须被修饰为抽象;抽象类无法实例化(new)。 abstract class DiQiuRen { public abstract void speak(); }
接口
1、接口是一种用来声明“能力”的类型,不提供具体实现 语法: public interface ISpeakable { void speak(); } 2、不提供实现方法,连{}都不能有。 3、接口无法实例化,只能被类“实现” public class TeacherCang : ISpeakable { } 4、既可以使用接口类型变量又可以使用类类型变量调用speak 5、接口的意义是定义“做什么”,类定义“怎么做” 6、接口中不能声明变量(字段),一个没有实现代码的接口中声明变量没意义。 7、接口中可以定义多个方法,也可以不定义任何方法(* 标识接口)。 8、接口只是“能力”不是“实现”,因此不能也必要定义构造函数。 9、类只能有一个父类,类可以实现多个接口。测试一下:Speakable、Walkable。
Winform窗口互相调用的对象问题
//可以通过对象属性,传递 //窗口1代码 private void btnOk_Click(object sender, EventArgs e) { Form2 f2 = new Form2(); f2.MainForm = this; f2.Show(); } //窗口2代码 public partial class Form2 : Form { public Form1 MainForm {get;set;} public Form2() { InitializeComponent(); } private void Form2_Load(object sender, EventArgs e) { } }
is和as
static void Main(string[] args) { Child c = new Child(); Parent p1 = new Parent(); Parent p2 = new Child();//Parent p2 = new Parent(); if (p2 is Child) { Console.WriteLine("是child类"); Child c2 = (Child)p2;//使用is提前判断,避免显示转换失败抛异常! } else { Console.WriteLine("不是child类"); } //is 用来判断一个变量指向的对象是否是指定类型(或者子类)的类型对象 //as 用来进行类型转换.如果转换失败则返回null. Child c3 = p2 as Child;//把p2显示转换为child 如果p2指向的不少child的类型 那么返回null if (c3 == null) { Console.WriteLine("不是child类"); } else { Console.WriteLine("是child类"); } Console.ReadKey(); } class Parent { } class Child : Parent { }
抽象类的抽象方法 ,子类必须包含此方法,抽象类允许有字段
virtual多态,子类里不必包含此方法
接口,里面只有方法.公开的方法
一个类允许多个接口,抽象类只允许一个