1.成员定义
成员变量:类中的字段,用于存储数据
成员函数:类中的函数,执行特定任务的语句
局部变量:方法体内的变量,方法中有效,var 能代替任意类型,必须初始化时赋值,且不能更改
值类型:是对类型的副本进行操作,如,基本数据类型,枚举,结构
引用类型:是对类型本体的引用,如,数组,接口,类(基类 Object,delegate,string)
2.可空类型
可空类型表示在基础值类型范围内,加上一个 null 值
1 int ? a = null; 2 int ? b = 3; 3 int ? c = 5; 4 int ? result_1 = a ?? b // 返回 3 5 int ? result_2 = c ?? b // 返回 5
3.Foreach 循环
1 int[] array = new int[3]{1,2,3}; // 遍历数组 2 3 foreach(int n in array) 4 { 5 Console.WriteLine("{0}",n); 6 }
4.方法
1 class Add 2 { 3 public int AddFun(int n) // 访问修饰符,返回值类型,方法名,参数列表,方法主体 4 { 5 int result; 6 7 if(n == 1) 8 { 9 return 1; 10 } 11 else 12 { 13 return result = n + AddFun(n-1); // 递归调用 14 } 15 } 16 } 17 18 Add A1 = new Add(); // 实例化后,使用函数名调用函数 19 int result = A1.AddFun(4); // 函数调用 20 21 Console.WriteLine("{0}",result);
值传递:实参和形参使用的是两个不同内存中的值,形参改变时,不会影响实参的值
引用传递:引用变量的内存位置,引用参数与实际参数具有相同的内存位置,ref 关键字引导,且变量必须初始化
1 class NumberSwitch 2 { 3 public void Switch(ref int a,ref int b) //交换变量 4 { 5 int Temp; 6 Temp = a; 7 a = b; 8 b = Temp; 9 } 10 11 public void Switch( int a, int b) //函数重载 12 { 13 int Temp; 14 Temp = a; 15 a = b; 16 b = Temp; 17 } 18 } 19 int a = 5; int b = 10; 20 NumberSwitch NS = new NumberSwitch(); 21 22 NS.Switch(a, b); //值传递 23 Console.WriteLine("{0},{1}",a,b); // 5,10 24 25 NS.Switch(ref a,ref b); //引用传递 26 Console.WriteLine("{0},{1}",a,b); // 10,5
5.数组
1 double[] array = new double[2]; // 一维数组 2 double[] array = new double[1,2] // 二维数组 3 4 array[0] = 1; array[1] = 2; // 索引号单独赋值 5 6 int[] array = {1,2}; // 声明后直接赋值 7 8 int[] array = new int[2] {1,2} //实例化后直接赋值,数组大小可省略 9 10 int[] score = array; // 把一个数组变量赋值到另一个数组中,而且指向相同的内存位置
6.字符串
String 变量直接定义,并使用串联运算符
1 string Fname,Lname; 2 Fname = "Zhang"; Lname = "San"; 3 4 string FullName = Fname + Lname ;
通过 string 构造函数
1 char[] letters = { 'H', 'e', 'l', 'l','o' }; 2 string welcome = new string(letters);
StringBuilder:通过 Append() 方法,修改字符串时自动扩展(适合大量字符串修改操作)
1 StringBuilder S1 = new StringBuilder(); 2 S1.Append("This is a StringBuilder");
7.结构体
可以带有多个成员的新数据类型,如:方法,字段,索引,属性,运算符方法和事件
结构不能继承其他的结构或类,但可以实现一个或多个接口
struct Books { public int id; // 不可赋值 public string name; } Books B1 = new Books(); // 实例化 B1.id = 1; B1.name = "西游记"; Console.WriteLine("{0} : {1}", B1.id,B1.name)
8.枚举
使用 enum 命名一组整型常量
1 enum Day { Sun, Mon, Tue, Wed, Thu, Fri, Sat } 2 3 int x = Convert.ToInt32(Day.Sun); // 默认从0开始 4 5 Console.WriteLine("{0}", x);
9.类
对象的集合,表示对象由什么组成,可执行什么操作,类中的方法和变量称为类的成员
多重继承:一个子类只能继承一个父类,但可以继承多个接口
1 class Box // 默认为 internal 2 { 3 public double lenth; // 默认为 private 4 public double breadth; 5 } 6 Box box = new Box(); 7 box.length = 10; 8 box.breadth = 10; 9 double Square = box.length * box.breadth; 10 11 Console.WriteLine("{0}", Square);
默认构造函数:初始化类实例,特殊的成员函数,类实例化对象时执行,无返回类型,与类名相同
1 public Box() 2 { 3 Console.WriteLine("对象已被创建"); 4 }
析构函数:无返回值,不带参数,有且只有一个,不能继承,用于程序结束之前释放资源
1 ~Box() 2 { 3 4 }
10.base
派生类继承基类的方法后,通过 base 实现方法内容,或创建派生类时,调用基类构造函数
1 class Father 2 { 3 protected string sex = "男"; 4 5 public virtual void GetInfo() // 父类方法 6 { 7 Console.WriteLine("{0}", sex); 8 } 9 10 public Father(int i) // 带参构造函数 11 { 12 Console.WriteLine("身高:{0}", i); 13 } 14 } 15 16 class Son : Father // 子类继承父类 17 { 18 public Son(int i) : base(i) // 通过 base 调用父类构造函数 19 { 20 21 } 22 23 public int age = 18; 24 25 public override void GetInfo() // 重写父类方法 26 { 27 base.GetInfo(); //通过 base 调用父类方法 28 Console.WriteLine("{0}", age); 29 } 30 } 31 Son S1 = new Son(170); // 实例化时,满足带参构造函数格式 32 S1.GetInfo();
11. this
表示当前类的实例,或充当方法的参数
1 class Tax 2 { 3 private static double salary = 3000.00; 4 5 public static double tax(Employee e) // 静态函数 6 { 7 return 0.1 * salary; 8 } 9 } 10 11 class Employee 12 { 13 private string name; 14 15 public Employee(string name) // 构造函数 16 { 17 this.name = name; // 使用 this 代表当前实例 18 } 19 20 public void PrintInfo() 21 { 22 Console.WriteLine("{0}:{1}", name, Tax.tax(this)); // 在方法中当作参数传递 23 } 24 } 25 Employee E1 = new Employee("Jhon"); 26 E1.PrintInfo();
12.堆和栈
引用类型:存储在堆中,类型实例化时,类的实例存储在堆中,类型对象的引用存储在栈中
值类型:值类型和指针分配在它声明的地方,做局部变量时,存储在栈上,做类对象的字段时,存储在堆中
1 Student S1;// S1是对象的引用 2 S1 = new Student(); // 实例化一个对象
托管堆:不同于 C 的堆,由 CLR 管理,当堆满后,自动清理堆中的垃圾
内存堆栈:内存分为栈区和堆区
:栈区存放函数参数,局部变量,返回值数据,由编译器自动释放
:堆区存放引用的对象,由CLR释放
装箱:把值类型转换为引用类型,把栈中的值封装起来,放在堆中存储
拆箱:先在栈中开辟一片空间,把堆中的数据复制到栈中
1 int Num_1 = 5; 2 object Num_2 = num_1; // 装箱 3 4 int Num_3; 5 Num_3 = (int) Num_2; // 拆箱
13.字段与属性
字段:在类中做数据交互使用,默认为 private
属性:外界访问私有字段的入口,本质是方法不保存数据,对字段进行赋值和读取操作
:首字母大写表示,默认为 public
class Student { private int age; // 私有字段 public int Age // 公有属性 { get // 获取 { if (age < 0) // 避免出现非法数据,或限定字段只读或只写 return 18; else return age; } set // 赋值 { age = value; } } public void PrintOut() { Console.WriteLine("{0}", Age); } } Student S1 = new Student(); S1.Name = -1; S1.PrintOut();
14.索引器
索引器可以使类或结构体的实例对象,以数组一样的方式进行索引,不能声明为 static
public class Student { private string[] name = new string[10]; // 定义数组,存储实例化对象 public string this[int index] // 索引器使用 this 定义,this 就是实例化后的对象 { // 索引类型可以是其他类型 get { return name[index]; } set { name[index] = value; } } } Student S1 = new Student(); S1[0] = "ZhangSan";
15.封装
访问修饰符:设置使用者的访问权限,确保数据成员安全
private:只能在在内部访问
protected:只有该类对象和子类对象可以访问
internal:同一个程序集可以访问
protected internal:允许在当前程序集,本类和派生类中访问
public:所有对象都可以访问
16.继承
派生类可以继承基类所有的属性和方法,且可以继承1个基类和多个接口
1 class Shape // 父类 2 { 3 public void setWidth(int w) 4 { 5 width = w; 6 } 7 protected int width; 8 } 9 10 class Square: Shape // 子类继承父类属性和方法 11 { 12 public int getArea() 13 { 14 return (width *width); 15 } 16 } 17 18 Square Rect = new Square(); 19 Rect.setWidth(5); 20 Rect.getArea();
17.多态性
多态就是同一个接口,使用不同的实例而执行不同操作
静态性多态:函数重载,运算符重载(不可使用 base 和 this)
函数重载:函数名相同,参数列表不同(数据类型,参数个数,参数顺序)
1 class Culculate 2 { 3 public void Cul(int a, int b) // 累加方法 4 { 5 int c = a + b; 6 Console.WriteLine("{0}", c); 7 } 8 9 public void Cul(double a, double b) // 函数重载 10 { 11 double c = a * b; 12 Console.WriteLine("{0}", c); 13 } 14 } 15 Culculate C1 = new Culculate(); 16 C1.Cul(1, 2); 17 C1.Cul(2.5, 2.5);
动态性多态:使用抽象类和虚方法实现
1 abstract class Shape // 抽象类:不能有方法体和实例化,只能在抽象类中声明抽象方法,子类必须重写 2 { 3 abstract public int area(); // 抽象方法 4 } 5 class Square: Shape 6 { 7 private int length; 8 9 public Square( int a = 0 ) // 构造函数,初始化 10 { 11 length = a; 12 } 13 public override int area () //重写父类方法,类似接口 14 { 15 Console.WriteLine("Square 类的面积:"); 16 return (length * length); 17 } 18 }19 Square S1 = new Square();20 Consolo.WriteLine("{0}",S1.arae()); 19 20 21 public class Shape 22 { 23 public virtual void Draw() // 虚方法:必须有方法体,子类不一定要重写 24 { 25 Console.WriteLine("父类方法"); // 实现部分 26 } 27 } 28 class Circle : Shape 29 { 30 public override void Draw() // 使用 override 重写父类方法 31 { 32 Console.WriteLine("重写父类方法"); 33 base.Draw(); // 调用父类方法 34 } 35 }16 Circle C1 = new Circle();17 C1.Draw();
18.接口
1 interface IClimbTree // 定义爬树接口 2 { 3 public void ClimbTree(); //只声明方法 4 } 5 6 interface ICatchMice // 定义抓老鼠接口 7 { 8 void CatchMice(); 9 } 10 11 class Cat : IClimbTree,ICatchMice // 类继承俩个接口 12 { 13 public void ClimbTree() // 在具体类中重写方法 14 { 15 Console.WriteLine("猫会爬树"); 16 } 17 public void CatchMice() 18 { 19 Console.WriteLine("猫会抓老鼠"); 20 } 21 } 22 23 Cat cat = new Cat(); 24 cat.ClimbTree(); 25 cat.CatchMice();
19.委托
本质是一个引用类型,对某个方法进行引用,间接调用方法,自身可作参数传递回调函数
1 public delegate int Delegate(int a, int b); // 定义委托,返回值类型和参数要与调用方法一致 2 3 class Culculator 4 { 5 public void Report() 6 { 7 Console.WriteLine("Have 3 Methods"); 8 } 9 public int Add(int a,int b) 10 { 11 return a + b; 12 } 13 public int Sub(int a,int b) 14 { 15 return a - b; 16 } 17 } 18 Culculator culculator = new Culculator(); 19 20 Action action = new Action(culculator.Report); // 内置 Action 委托,适合无返回类型 21 action.Invoke(); 22 // 内置 Func 委托,参数列表和返回值类型要对应 23 Func<int, int, int> func = new Func<int, int, int>(culculator.Add); 24 func.Invoke(5, 10); // Invoke() 调用函数 25 Console.WriteLine("{0}", func.Invoke(5, 10)); 26 27 Delegate dele = new Delegate(culculator.Sub); // 自定义委托 28 dele.Invoke(5, 5); 29 Console.WriteLine("{0}",dele(5, 5));
20.事件
事件在类中声明,是类的成员,使对象或类具备通知能力
如:对象 O 拥有事件 E,如果 B 订阅 O,当事件触发时,O 就会通知 B,B 根据事件参数做出反应(可选)
事件拥有者(event source,对象)
事件成员(event,成员)
事件的响应者(event subscriber,对象)
事件处理器(event handler,成员):本质是一个回调方法
事件订阅:把事件处理器与事件相关联,本质是一种委托
1 using System.Timers; // 内置事件 2 3 static void Main() 4 { 5 Timer timer = new Timer(); // 事件拥有者 6 timer.Interval = 1500; // 时间间隔,单位毫秒 7 8 Boy boy = new Boy(); // 事件响应者 9 10 timer.Elapsed += boy.Aciton; // 订阅事件,Elapsed 为事件 11 12 timer.Start(); // 计时开始 13 Console.ReadKey(); 14 } 15 16 class Boy 17 { 18 internal void Aciton(object sender, ElapsedEventArgs e) // 事件处理器 19 { 20 Console.WriteLine("触发事件"); 21 } 22 }
自定义时间:通过委托关联事件,从而调用函数
1 public delegate void CatCallEventHandler(); // 定义猫叫委托 CatCallEventHandler() 2 3 public class Cat // 发布器类 4 { 5 public event CatCallEventHandler CatCall; // 定义猫叫事件 CatCall 6 public void Call() 7 { 8 Console.WriteLine("猫叫了"); 9 CatCall?.Invoke(); // 事件不为空,则调用 10 } 11 } 12 13 public class Mouse // 订阅器类 14 { 15 public void Run() // 事件处理器 16 { 17 Console.WriteLine("老鼠跑了"); 18 } 19 } 20 21 public class People // 订阅器类 22 { 23 public void WakeUp() // 事件处理器 24 { 25 Console.WriteLine("人醒了"); 26 } 27 } 28 29 Cat cat = new Cat(); // 事件拥有者 30 Mouse mouse = new Mouse(); // 事件响应者 31 People people = new People(); 32 33 cat.CatCall += new CatCallEventHandler(mouse.Run); // 关联事件 34 cat.CatCall += new CatCallEventHandler(people.WakeUp); 35 36 cat.Call(); // 触发事件