C#核心 导航 请根据右侧目录进行自助跳转
类名
{ 
 (写在类中的)
    成员变量 
    成员方法 
    初始化调用-构造函数 
    释放时调用-析构函数 
    成员属性 
    索引器 
    静态成员-类名点出使用 
    运算符重载 
}
(写在类外的)
静态类和静态构造函数 
拓展方法 
类和对象 什么是类 基本概念: 
具有相同特征 
具有相同行为 
一类事物的抽象 
类是对象的模板 
可以通过类创建出对象 
类的关键词:class 
 
类声明在哪里 一般声明在namespace的语句块中
类声明的语法 1 2 3 4 5 6 7 8 9 10 访问修饰符(pubic,private ) class  类名 {                                    } 
类声明实例 1 2 3 4 5 6 7 8 9 10 11 12 13 class  Person {                                    } 
什么是(类)对象 基本概念:
类的声明 和类对象(变量)声明 是两个 概念类的声明类似枚举 和结构体 的声明,类的声明相当于声明了一个自定义的变量类型 
而对象是类创建出来的 
相当于声明一个指定类的变量 
类创建对象的过程一般称为实例化对象 
类对象都是引用类型 的(数组 string都是引用类型  而 结构体是值类型) 
 
实例化对象的基本语法 实例化对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 using  System;class  Person { } class  Program {     static  void  Main (string [] args     {         Person p;         Person p2 = null ;         Person p3 = new  person();         Person p4 = new  person();                                } } 
练习题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 using  System;class  GameObject { } class  Program {     static  void  Main (string [] args     {     	GameObject A = new  GameObject();     	GameObject B=A;     	B= null ;                  GameObject A = new  GameObject();     	GameObject B=A;     	B= new  GameObject();              } } 
答案 1.因为类是一个引用类型,所以B=A实际上是在栈中创建了两个不同的空间,但是二者的地址相同因此所指向堆中的空间也相同。但是B=NULL,是将栈中的B所占有的空间替换为空,从而没有影响到堆中的空间。因此A不受影响,等于原来的值 
2.和上题一样,都是在栈中创建了两个不同的空间,一开始令B=A使B与A都指向了堆中相同的空间,但后来B= new GameObject();使B在堆中又创立了一个不同的空间,因此在堆中指向的空间也不同。所以A与B没有关系 
成员变量和访问修饰符 成员变量 
基本规则: 
声明在类语句块中 
用来描述对象的特征 
可以是任意变量类型 
数量不做限制 
是否赋值根据需求来定 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 enum  E_SexType{     Man,     Woman, } struct  Position{      } class  pet {      } class  Person {               string  name = '铅笔沫' ;          int  age;          E_SexType sex;          Person grilFriend;          Person[] boyFriend;          Postion pos;          Pet pet; } 
访问修饰符 
public—公共的
private—私有的
protected—保护的
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 using  System;enum  E_SexType{     Man,     Woman, } struct  Position{      } class  pet {      } class  Person {               public  string  name = '铅笔沫' ;          public  int  age;          public  E_SexType sex;                    public  Person grilFriend;          public  Person[] boyFriend;          public  Postion pos;          public  Pet pet; } class  Program {     static  void  Main (string [] args     {         Person p = new  Person();     } } 
成员变量的使用和初始值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class  Program {     static  void  Main (string [] args     {         Person p = new  Person();                                             Console.WriteLine(default (bool ));         Console.WriteLine(default (int ));          Console.WriteLine(default (Person));          p.age = 10 ;         Console,WriteLine(p.age);		     } } 
练习题 Q1:3p是什么 Q2:定义一个人类 Q3:定义一个学生类(带有同桌) Q4:定义一个班级类(专业名称,教师容量,学生) Q5:请问p.age为多少 1 2 3 4 Person p = new  Person(); p.age = 10 ; Person p2 = new  Person(); p2.age = 20 ; 
Q6:请问p.age为多少 1 2 3 4 Person p = new  Person(); p.age = 10 ; Person p2 = p; p2.age = 20 ; 
Q7:请问s.age为多少 1 2 3 4 Student s = new Student(); s,age = 10; int age = s.age; age = 20; 
Q8:请问s.deskmate.age为多少 1 2 3 4 5 Student s = new  Student(); s.deskmate = new  Student(); s.deskmate.age = 10 ; Student s2 = s.deskmate; s2.age = 20 ; 
答案 A1: private,public,protected 
A2: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class  Person {     public  string  name;     public  int  age;     public  string  homeAddress; } class  Program {     static  void  Main (string [] args     {         Person p = new  Person();         p.age = 18 ;         p.name ='铅笔沫' ;         p.homeAddress = '佳木斯' ;              } } 
A3: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class  Student {     public  string  name;     public  int  age;     public  string  homeAddress;     public  Student deskMate; } class  Program {     static  void  Main (string [] args     {         Student p = new  Student();         p.age = 18 ;         p.name ='铅笔沫' ;         p.homeAddress = '佳木斯' ;         Student p2 = new  Student();         p2.age = 18 ;         p2.name ='云笙繁华' ;         p2.homeAddress = '佳木斯' ;         p.deskMate = p2;         p2.deskMate = p;     } } 
A4: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class  CLass (){     public  string  name;     public  int  capacity;     public  Student[] students; } class  Student {     public  string  name;     public  int  age;     public  string  homeAddress;     public  Student deskMate; } class  Program {     static  void  Main (string [] args     {         Student p = new  Student();         p.age = 18 ;         p.name ='铅笔沫' ;         p.homeAddress = '佳木斯' ;         Student p2 = new  Student();         p2.age = 18 ;         p2.name ='云笙繁华' ;         p2.homeAddress = '佳木斯' ;         p.deskMate = p2;         p2.deskMate = p;         Class c = new  Class();         c.name = "Unity" ;         c.capacity = 99999 ;         c.student = new  student[] {p,p2};     } } 
A5: 10 
A6: 二者指向地址相同,因此 p2,age = 20 与 p.age =20一致,因此p,age=20 
A7: 因为age是一个值类型,没有通过地址改变s,age的值所以s,age 仍然等于10 
A8: 因为Student s2 = s.deskmate 指向的同一个地址因此s2.age = 20 等价于 s.deskmate.age = 20 
成员方法 成员方法的声明 基本概念: 
成员方法(函数)用来表现对象的行为 
声明在类语句块中 
适应来描述对象的行为 
规则和函数声明规则相同 
受到访问修饰符的规则影响 
返回值函数不做限制 
 
注意: 
成员方法不要加static关键字 
成员方法 必须实例化出对象 再通过对象来使用 相当于该对象执行了某个行为 
成员方法 收到访问修饰符的影响 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 class  Person {     public  string  name;     public  int  age;         public  void  Speak (string  str     {         Console.WriteLine("{0}说{1}," name.str);     }     public  bool  IsAdult ()     {         return  age >= 18 ;     } } 
成员方法的使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 class  Person {     public  string  name;     public  int  age;     public  Person[] friends;         public  void  Speak (string  str     {         Console.WriteLine("{0}说{1}," name.str);     }     public  bool  IsAdult ()     {         return  age >= 18 ;     }     public  AddFriend (Person p )     {         if (friends == NULL)         {             friends = new  Person[] {p};         }         else          {                          Person[] newFriends = New Person[friends.Length + 1 ];                          for (int  i =0 ;i<friends.Length;i++)             {                 newFriends[i]=friends[i];             }                          newFriends[newFriends.Length-1 ]=p;                          friends = Newfriends;         }     } } class  Program {     static  void  Main (string [] args     {                  Person p = new  Person();         p.name = "铅笔沫" ;         p.age =18 ;         p.Speak("你好呀" );         p.IsAdult();         Person p2 = new  Person();         p2.name = "云笙繁华" ;         p2.age =18 ;         P.AddFrind(p2);         for (int  i=0 ; i<p.friends.Length;i++)         {             Console.WriteLine(p.Friends[i],name);         }     } } 
练习题 Q1:为人类定义说话,吃饭,走路等方法 Q2:定义一个食物类,有名称,热量等特征,并将其与人类和学生类联系起来 答案 A1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 using  System;namespace  Homework {     class  People      {         public  string  name;         public  int  age;         public  float  height;         public  string  homeAddress;         public  void  Speak (string  str         {             Console.WriteLine("{0}说{1}" , name, str);         }                 public  void  Walk ()         {             Console.WriteLine("{0}开始走路了" , name);         }         public  void  Eat ()         {             Console.WriteLine("{0}开始吃饭了" , name);         }     }     class  Program      {         static  void  Main (string [] args         {             People p = new  People();             p.name = "1111" ;             p.Speak("222222" );             p.Walk();             p.Eat();         }     } } 
A3: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 using  System;namespace  Homework {     class  food      {         public  string  name;         public  int  kaluli;     }     class  People      {         public  string  name;         public  int  age;         public  float  height;         public  string  homeAddress;         public  void  Speak (string  str         {             Console.WriteLine("{0}说{1}" , name, str);         }         public  void  Walk ()         {             Console.WriteLine("{0}开始走路了" , name);         }         public  void  Eat (food f )         {             Console.WriteLine("{0}开始吃{1}" , name,f.name);         }     }         class  Student      {         public  string  name;         public  int  age;         public  float  height;         public  string  homeAddress;        public  void  Learn ()         {             Console.WriteLine("{0}在学习" , name);         }         public  void  Eat (food f )         {             Console.WriteLine("{0}开始吃{1}" , name,f.name);         }     }     class  Program      {         static  void  Main (string [] args         {             People p = new  People();             p.name = "1111" ;             Student s = new  Student();             s.name = "abcd" ;             food f = new  food();             f.name = "3333" ;             p.Eat(f);             s.Eat(f);         }     } } 
构造函数和析构函数 构造函数 基本概念: 
在实例化对象时 会调用的用于初始化的函数 
如果不写默认存在一个无参构造函数 
 
构造函数的写法 
没有返回值 
函数名和类名必须相同 
没有特殊需求是 一般都是public的 
构造函数可以被重载 
this代表当前调用该函数的对象自己 
 
注意: 如果声明了有参构造而没有声明无参构造,则不能使用无参构造去实例化对象
参考C++
this.的用法 1 2 3 4 5 6 7 8 class  Person {     public  Person (int  age     {                	this .age = age;     } } 
构造函数的特殊写法 可以通过this 重用构造函数代码
访问修饰符 构造函数名(参数列表):this(参数1,参数2…..)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class  Person {     public  Person ()     {         name = "云笙繁华" ;         age = 18 ;     }     public  Person (int  age,string  namethis () 	{     	Console.WriteLine("两个参数构造函数调用" ); 	} } class  Program {     static  void  Main (string [] args     {         Person p = new  Person(18 ,"铅笔沫" );         Console.WriteLine(p.age);     } } 
使用这种特殊写法,会先调用this()(无则无参,有则对应到this里对应内容的函数),之后再调用该函数中的内容,并且this中的内容可以写死,或者进行默认的增减调整,会自动根据类型转到对应的函数
析构函数 基本概念: 
当引用类型的堆内存被回收时,会调用该函数 
对于需要手动管理内存的语言(比如C++),需要在析构函数中做一些内存回收处理 
但是C#中存在自动垃圾回收机制GC 
所以我们几乎不会怎么使用析构函数,除非你想在某一个对象被垃圾回收时,做一些特殊处理 
在垃圾真正被回收的时候,才会调用的函数 
 
注意: 在Unity开发中析构函数几乎不会使用
基本语法: 垃圾回收机制 垃圾回收,英文简写GC(Garbage Collector) 垃圾回收的过程是在遍历堆(Heap)上动态分配的所有对象
通过识别它们是否被引用来确定哪些对象是垃圾,哪些对象仍要被引用
所谓的垃圾就是没有被任何变量,对象引用的内容
垃圾就需要被回收释放
垃圾回收有很多种算法,比如 引用计数(Reference Counting)
标记清楚(Mark Sweep)
标记整理(Mark Compact)
复制整合(Copy Collection)
注意: GC只负责堆(Heap)内存的垃圾回收 
引用类型都是存在堆(Heap)中的,所以它的分配和释放都通过垃圾回收机制来管理
栈(Stack)上的内存是由系统自动管理的
值类型在栈(Stack)中分配内存的,他们有自己的生命周期,不用对他们进行管理,会自动分配和释放
C#中内存回收机制的大概原理 0代内存 1代内存 2代内存
代的概念:
代是垃圾回收机制使用的一种算法(分代算法)
新分配的对象都会被配置在第0代内存中
每次分配都可能会进行垃圾回收以释放内存(0代内存满时)
在一次内存回收过程开始时,垃圾回收器会认为堆中全是垃圾,会进行以下两步
1.标记对象从根(静态字段、方法参数)开始检查引用对象,标记后为可达对象,未标记为不可达对象//不可达对象就认为是垃圾
2.搬迁对象压缩堆―(挂起执行托管代码线程)释放未标记的对象搬迁可达对象修改引用地址
大对象总被认为是第二代内存目的是减少性能损耗,提高性能
不会对大对象进行搬迁压缩8500o字节(83kb)以上的对象为大对象
简而言之,0代内存满时,触发GC将不可达对象清除,将可达对象转移至1代内存,当1代内存满时,再次触发GC,将可达对象转移至2代内存,并且将0、1代内存同时清空。 
手动触发GC 一般情况下 我们不会频繁调用
都是在 Loading过场景时 才调用
练习题 Q1:基于成员方法,对人类的构造函数进行重载,用人类创建若干个对象 Q2:基于成员变量,对班级类的构造函数进行重载,用班级类创建若干个对象 Q3:写一个Ticket类 写一个Ticket类,有一个距离变量(在构造对象时赋值,不能为负数),有一个价格特征,有一个方法GetPrice可以读取到价格,并且根据距离distance计算价格price ( 1元/公里)
0~100公里不打折
101~200公里打9.5折
201~300公里打9折
300公里以上打8折
有一个显示方法,可以显示这张票的信息。
例如:100公里100块钱
答案 A1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 using  System;namespace  Homework {     class  Food      {         public  string  name;         public  int  kaluli;     }     class  People      {         public  string  name;         public  int  age;         public  float  height;         public  string  homeAddress;         public  void  Speak (string  str         {             Console.WriteLine("{0}说{1}" , name, str);         }         public  void  Walk ()         {             Console.WriteLine("{0}开始走路了" , name);         }         public  void  Eat (Food f )         {             Console.WriteLine("{0}开始吃{1}" , name,f.name);         }         public  People (string  name,float  height,int  age,string  homeAddressthis (name,height )         {             this .age = age;             this .homeAddress = homeAddress;         }         public  People (string  name,float  height         {             this .name = name;             this .height = height;         }     }     class  Program      {         static  void  Main (string [] args         {             People p1 = new  People("铅笔沫" , 177 , 19 , "佳木斯" );             People p2 = new  People("云" ,165 , 18 , "佳木斯" );         }     } } 
A2: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 using  System;namespace  Homework {     class  Food      {         public  string  name;         public  int  kaluli;     }     class  Class      {         public  string  name;         public  int  capacity;         public  Student[] students;         public  Class (string  name,int  capacity         {             this .name = name;             this .capacity = capacity;         }                  public  Class (string  name,int  capacity ,Student[] studentsthis (name,capacity )         {             this .students = students;         }     }     class  Student      {         public  string  name;         public  int  age;         public  float  height;         public  string  homeAddress;         public  void  Learn ()         {             Console.WriteLine("{0}在学习" , name);         }         public  void  Eat (Food f )         {             Console.WriteLine("{0}开始吃{1}" , name, f.name);         }     }     class  People      {         public  string  name;         public  int  age;         public  float  height;         public  string  homeAddress;         public  void  Speak (string  str         {             Console.WriteLine("{0}说{1}" , name, str);         }         public  void  Walk ()         {             Console.WriteLine("{0}开始走路了" , name);         }         public  void  Eat (Food f )         {             Console.WriteLine("{0}开始吃{1}" , name,f.name);         }         public  People (string  name,float  height,int  age,string  homeAddressthis (name,height )         {             this .age = age;             this .homeAddress = homeAddress;         }         public  People (string  name,float  height         {             this .name = name;             this .height = height;         }     }     class  Program      {         static  void  Main (string [] args         {             People p1 = new  People("铅笔沫" , 177 , 19 , "佳木斯" );             People p2 = new  People("云" ,165 , 18 , "佳木斯" );             Class c1 = new  Class("Unity" , 999999 );             Student s1 = new  Student();             Student s2 = new  Student();             Class c2 = new  Class("C#" , 999999 ,new  Student[] {new  Student(),new  Student()});         }     } } 
A3: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 using  System;namespace  Homework {     class  Food      {         public  string  name;         public  int  kaluli;     }     class  Class      {         public  string  name;         public  int  capacity;         public  Student[] students;         public  Class (string  name,int  capacity         {             this .name = name;             this .capacity = capacity;         }                  public  Class (string  name,int  capacity ,Student[] studentsthis (name,capacity )         {             this .students = students;         }     }     class  Student      {         public  string  name;         public  int  age;         public  float  height;         public  string  homeAddress;         public  void  Learn ()         {             Console.WriteLine("{0}在学习" , name);         }         public  void  Eat (Food f )         {             Console.WriteLine("{0}开始吃{1}" , name, f.name);         }     }     class  People      {         public  string  name;         public  int  age;         public  float  height;         public  string  homeAddress;         public  void  Speak (string  str         {             Console.WriteLine("{0}说{1}" , name, str);         }         public  void  Walk ()         {             Console.WriteLine("{0}开始走路了" , name);         }         public  void  Eat (Food f )         {             Console.WriteLine("{0}开始吃{1}" , name,f.name);         }         public  People (string  name,float  height,int  age,string  homeAddressthis (name,height )         {             this .age = age;             this .homeAddress = homeAddress;         }         public  People (string  name,float  height         {             this .name = name;             this .height = height;         }              }     class  Ticket      {         public  uint  distance;         public  float  price;         public  Ticket (uint  distance         {             this .distance = distance;             price = GetPrice();         }         private  float  GetPrice ()         {             if (distance >300 )             {                 return  distance * 0.8f ;             }             else  if (distance>=201 &&distance<=300 )             {                 return  distance * 0.9f ;             }             else  if (distance>=101 &&distance<=200 )             {                 return  distance * 0.95f ;             }             else              {                 return  distance;             }         }         public  void  ShowInfo ()         {              Console.WriteLine("{0}公里{1}块钱" ,distance,price);         }     }     class  Program      {         static  void  Main (string [] args         {             People p1 = new  People("铅笔沫" , 177 , 19 , "佳木斯" );             People p2 = new  People("云" ,165 , 18 , "佳木斯" );             Class c1 = new  Class("Unity" , 999999 );             Student s1 = new  Student();             Student s2 = new  Student();             Class c2 = new  Class("C#" , 999999 ,new  Student[] {new  Student(),new  Student()});         }     } } 
成员属性 基本概念 与c++类似
public—公共
private—私有
protected—保护
基本语法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class  Person {     private  string  name;     private  int  age;     private  int  money;     public  string  Name     {         get          {	                                                    return  name;         }         set          {                                                    name = value ;                    }     }     public  int  Money     {      	get          {                          return  monet-5 ;         }         set          {                          money=value +5 ;         }     } } 
使用方法 1 2 3 4 5 6 7 8 9 10 class  Progarm {     static  void  Main (string[] args)       {        Console.WriteLine ("成员属性" );         Person p = newPerson ();         p.Name = "qianbimo" ;         Console.WriteLine (p.name);     } } 
访问修饰符 PS:
1.默认不加 会使用属性中声明的访问权限
2.加的访问修饰符要低于属性的访问权限
3.不能让get和set的访问权限都低于属性的权限
Public>Private>Protected 
可以解决3P的局限性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public  int  Money{     get      {         return  money - 5 ;     }     set      {         money = value  + 5 ;     }      } 
get  和 set 可以只有一个 意思是,在一个成员中 可以只有get或set其中一个。
一般用在 只希望得到数据 但是不希望让他人获得数据的时候
而且因为只有一个 get 或者 set  所以完全不需要 在前面加上访问修饰符。
其实说人话,就是在于,只读与只写 的不同罢了。
1 2 3 4 5 6 7 pubilc bool  Sex {     get       {         return  sex;     } } 
自动属性 作用就在于,外部能得但是不能改的特征
如果类中有一个特征是只希望外部能得 ,不能改 的,又没什么特殊处理
那么可以直接使用自动属性
1 2 3 4 5 6 public  float  Height{          get ;     set ; } 
在这里 会自动设定一个 变量  将获取到的值蕴含在里面
练习题 Q1: 定义一个学生类,有五种属性,分别为姓名,性别,年龄,Csharp成绩,Unity 成绩
有两个方法:
一个打招呼,介绍自己叫xxx,今年几岁了,性别是什么,计算自己的总分数和平均分并显示的方法
使用属性完成:年龄必须是0~150 岁之间,成绩必须是 0~100
性别只能是男女
实例化两个对象并测试。
A1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 using  System;using  System.Runtime.InteropServices;namespace  Homework {     class  Student      {         private  int  age;         private  int  csharp;                private  int  unity;         private  string  sex;         public  string  Name          {             get ;              set ;          }         public  string  Sex         {             get              {                 return  sex;             }             set              {                 if (value  !="男" &&value !="女" )                 {                     sex = "不男不女" ;                 }                 else                  {                     sex = value ;                 }             }         }         public  int  Age         {             get              {                 return  age;             }             set              {                 if  (value  < 0 )                 {                     age = 0 ;                 }                 else  if  (value  > 150 )                 {                     age = 150 ;                 }                 else                  {                     age = value ;                 }             }         }         public  int  Csharp         {             get              {                 return  csharp;             }             set              {                 if  (value  < 0 )                 {                     csharp = 0 ;                 }                 else  if  (value  > 100 )                 {                     csharp = 100 ;                 }                 else                  {                     csharp = value ;                 }             }         }          public  int  Unity         {             get              {                 return  unity;             }             set              {                 if  (value  < 0 )                 {                     unity = 0 ;                 }                 else  if  (value  > 100 )                 {                     unity = 100 ;                 }                 else                  {                     unity = value ;                 }             }         }         public  void  SayHello ()         {             Console.WriteLine("我叫{0},今年{1}岁了,是{2}同学" ,Name,Age,Sex);         }         public  void  ShowInfo ()         {             int  sum = Csharp+Unity;             float  avg = sum / 2f ;             Console.WriteLine("总分{0},平均分{1}" , sum, avg);         }     }     class  Program      {         static  void  Main (string [] args         {             Student s1 =new  Student();             s1.Name = "铅笔沫" ;             s1.Age = 114514 ;             s1.Unity = 1919810 ;             s1.Csharp = 1545454 ;             s1.Sex = "男" ;             s1.SayHello();             s1.ShowInfo();                          Student s2 =new  Student();             s2.Name = "云笙繁华" ;             s2.Age = 18 ;             s2.Unity = -100 ;             s2.Csharp = 100 ;             s2.Sex = "女" ;             s2.SayHello();             s2.ShowInfo();         }     } } 
索引器 基本概念 让对象可以像数组一样通过索引访问其中的元素,使程序看起来更直观,更容易编写
基本语法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 访问修饰符 返回值 this [参数类型 参数名,参数类型 参数名.....] {     内部的写法和规则和索引器相同     get {};     set {}; } class  Person {     private  string  name;     private  int  age;     private  Person[] friends;          public  Person this [int  index]     {         get          { 			return  friends[index];         }         set          { 			             friends[index] = value ;         }     } } 
使用方法 1 2 3 4 5 6 7 8 9 10 class  Program {     static  void  Main (string []args     {         Console.WriteLine("索引器" );         Person P = new  Person();         p[0 ] = new  Person();         Console.WriteLine(p[0 ]);     } } 
索引器中可以写逻辑 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public  Person this [int  index]{ 	get      {                  if (friends == null  || friends.Length - 1 <index)         {             return  null ;         }     }     set      {         if (friends == null )         {             friends = new  Person[]{value };         }         friends[index] = value ;     } } 
索引器可以重载 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 class  Person {     private  string  name;     private  int  age;     private  Person[] friends;     private  int [,] array;               public  int  this [int  i,int  j]     {         get          {             return  array[i,j];         }         set          { 			array[i,j]=value ;         }     }     public  int  this [string  str]     {         get          {             switch (str)             {                 case  "name" :             		return  this .name;                 case  "age" :                     return  age.ToString();             }             return  "" ;         }     }     public  Person this [int  index]     {         get          { 			return  friends[index];         }         set          { 			             friends[index] = value ;         }     } } class  Program {     static  void  Main (string []args     {         Console.WriteLine("索引器" );         Person P = new  Person();         p[0 ] = new  Person();         Console.WriteLine(p[0 ]);                  p[0 ,0 ] =10 ;     } } 
练习题 Q1: 自定义一个整型数组类,该类中有一个整型数组变量为它封装增删查改的办法
静态成员 基本概念 静态关键字 static 
用 static 修饰的 成员变量、方法、属性等
特点 类名.变量名称就是静态变量
自定义静态成员 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class  Test {          public  static  float  PI = 3.1415926 ; 	     public  int  TestInt = 100 ;          public  static  float  CalcCircle (float  r     {         return  PI * r * r;     }     public  void  TestFun ()     {         Console.WriteLine("123" );     } } 
使用方法 1 2 3 4 5 6 7 8 9 10 11 class  Program {     static  void  Main (string [] args     {         Console.WriteLine(Test.PI);         Console.WriteLine(Test.CalcCricle(2 ));         Test t = new  Test();         Console.WriteLine(t.testInt);         t.Testfun();     } } 
为什么静态变量可以直接进行使用 众所周知,程序不能无中生有,实例化对象的目的就是为对象等进行分配空间。那为什么静态变量就可以直接使用呢?
静态成员的特点:
静态变量有一个属于自己的大空间叫做静态存储区 
1.程序开始运行时 就会分配内存空间,所以就可以直接使用
2.静态成员和程序同生共死
3.只有使用静态变量,程序结束时内存空间才会释放,所以一个静态成员就会有自己唯一的一个”内存小房间”,这就让静态成员有了自己的唯一性 。
4.在任何地方使用都是用小房间的内容,改变的也是房间内的内容。
静态函数中不能使用非静态成员 成员变量只能将对象实例化出来后 才能点出来使用  不能无中生有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class  Test {          public  static  float  PI = 3.1415926 ; 	     public  int  TestInt = 100 ;          public  static  float  CalcCircle (float  r     {         return  PI * r * r;                                             Test t = new  Test();         Console.WriteLine(t.testInt);     }     public  void  TestFun ()     {         Console.WriteLine("123" );     } } 
非静态函数可以使用静态成员 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class  Test {     public  static  float  PI = 3.1415926 ;          public  int  TestInt = 100 ;          public  static  float  CalcCircle (float  r     {         return  PI * r * r;     }     public  void  TestFun ()     {         Console.WriteLine("123" );         Console.WriteLine(PI);         Console.WriteLine(CalcCricle);     } } 
常量和静态变量 const(常量)可以理解为特殊 的static(静态)
相同点:
都可以通过类名.出
不同点:
1.const必须初始化不能修改,static没有这种限制
2.const只能修饰变量,static可以修修很多
3.const一定是卸载访问修饰符后面的,static没有这个要求
 
练习题 Q1: 请说出const与static的区别
Q2: 请用静态成员来实现
一个类对象在整个应用程的生命周期中,有且仅会有一个该对象不存在,不能再外部实例化,直接通过该类类名就能得到唯一的对象
静态类和构造函数 静态类 基本概念 用static修饰的类 
特点 只能包含静态成员,不能被实例化 更适合被当作工具类 
作用 1.将常用的静态成员写在静态类中 方便使用
2.静态类不能被实例化,更能体现工具类的 唯一性 
比如 Console就是一个静态类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 using  System;namespace  std {     static  class  value      {                           public  static  int  testIndex =0 ;         public  static  void  TestFun ()         {                      }         public  static  int  TestIndex         {             get ;             set ;         }     }     class  Program      { 		static  void  Main (string [] args         {             Console.WhiteLine(”铅笔沫“);         }     } } 
静态构造函数 基本概念 在构造函数之前加上 static 修饰
特点 1.静态类和普通类都可以有
2.不能使用访问修饰符
3.不能有参数
4.只会自动调用一次
作用 在静态构造函数中初始化 静态变量
使用 静态类中的静态构造函数 1 2 3 4 5 6 7 8 9 static  class  StaticClass { 	public  static  int  testInt = 100 ;     public  static  int  testInt2 = 100 ;     static  StaticClass     { 		Console.WhiteLine("调用静态构造函数" );     } } 
调用顺序 在第一次使用静态类时,就会自动调用一次静态构造函数 
普通类中的静态构造函数 1 2 3 4 5 6 7 8 9 10 11 12 class  Test {     public  static  int  testInt =200 ;     static  Test ()     {         Console.WriteLine("静态构造" );     }     public  Test ()     {         Console.WriteLine("普通构造" );     } } 
调用顺序 在第一次使用普通类时,就会自动优先调用一次静态构造函数 
练习题 Q1: 写一个用于数学计算的静态类
对类中提供计算圆面积,圆周长,矩形面积,矩形周长,取个数的绝对值方法等
拓展方法 基本概念 为现有的非静态 变脸类型 添加 新方法
作用 1.提升程序的拓展性
2.不需要在对象中重新写方法
3.不需要继承来添加方法
4.为别人封装的类型写额外的方法
特点 1.一定写在静态类当中的
2.一定是个静态函数
3.第一个参数为拓展目标
4.第一个参数用this修饰
基本语法及其使用 3P访问修饰符 static 返回值 函数名(this 拓展类名 参数名,参数类型 参数名,参数类型 参数名........)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 using  System;namespace  std ;{     static  class  Tools      {                                             public  static  void  SpeakValue (this  int  value          {                          Console.WriteLine("int的拓展方法" +value );           }                  public  static  void  SpeakStringInfo (this  string  str, string  str2,string  str3         {             Console.WriteLine("string的拓展方法" );             Console.WriteLine("调用的对象" +str);             Console.WriteLine("传的参数" +str2+str3);         }     }     class  Program      {         static  void  Main (string [] args         {             int  i = 10 ;                          i.SpeakValue();             string  str = "000" ;             str.SpeakStringInfo("111" ,"222" );         }     } } 
自定义类型的拓展方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 using  System;namespace  std ;{     class  Test      {         public  i =10 ;         public  void  Fun1 ()         {             Console.WriteLine("123" );         }         public  void  Fun2 ()         {             Console,WriteLine("456" );         }     }     public  static  void  Fun3  (this  Test t     {         Console.WhiteLine("为test拓展的方法" );     }     class  Program      {         static  void  Main (string [] args         {             Test t = new  Test();             t,Fun3();         }     } } 
注意:如果新加入的方法和原有的方法重名,则会优先调用原有的方法! 
练习题 Q1: 为整形拓展一个求平方的方法
Q2: 写一个玩家类,包含姓名,血量,攻击力,防御力等特征,攻击,移动,受伤等方法
运算符重载operator 基本概念 让自定义的类与结构体,能够使用运算符
特点 
一定是一个公共的静态方法 
返回值写在operator之前 
逻辑处理自定义 
返回值自定义 
 
注意 
条件运算符需要成对实现 
一个符号可以多个重载 
不能使用ref和out 
 
基本语法 public static 返回类型 operator 运算符(参数列表)
实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class  Point {     public  int  x;     public  int  y;          public  static  Point operator  +(Point p1,Point p2)     { 		Point p = new  point();         p.x=p1.x+p2.x;         p.y=p1.y+p2.y;         return  p;    	}     public  static  Point operator  +(Point p1,int  a)     { 		Point p = new  point();         p.x=p1.x+a;         p.y=p1.y+a;         return  p;    	} } 
使用 1 2 3 4 5 6 7 8 9 Point p = new  Point(); p.x = 1 ; p.y = 1 ; Point p1 =new  Ponit(); P1.x = 2 ; p1.y = 2 ; Point p3 = p+p1; Point p4 = p+2 ; 
可重载和不可重载的运算符 可重载的运算符 ()内部写的是需要传几个参数
算术运算符 +(2) -(2) *(2) /(2) %(2) ++(1) --(1)
逻辑运算符 !(1)
看到这里,你可能会疑惑,我要怎么去重载!这个运算符呢?
其实没有必要去纠结,运算符重载是很自由的,你可以自定义返回,它是布尔类型 还是整形 ,抑或是浮点数 
举个例子
1 2 3 4 5 6 7 8 9 10 11 public  static  bool  operator  !(Point p1){     return  false ; } 
那么与(&&)或(||)这两个运算符呢,很遗憾的是,他们两个并不支持去重载。
位运算符 |(2) &(2) ^(2) ~(1) <<(2) >>(2)
条件运算符 >(2) <(2) >=(2) <=(2)
值得注意的是,刚才在上方我们也说了,条件运算符要成对出现。这代表着什么意思呢?
是说明,当存在>重载时,<也必须跟着重载 
不可重载的运算符 
逻辑与(&&) 逻辑或(||) 
索引符([]) 
强转运算符(()) 
特殊运算符(点.三目运算符? :赋值符号 =) 
 
练习题 Q1: 定义一个位置结构体或类,为其重载判断是否相等的运算符(x1,y1)==(x2,y2)两个值相同时才为true
Q2: 定义一个Vector3类(x,y,z)通过重载运算符实现以下运算
(x1,y1,z1)+(x2,y2,z2)=(x1+x2,y1+y2,z1+z2)
(x1,y1,z1)-(x2,y2,z2)=(x1-x2,y1-y2,z1-z2)
(x1,y1,z1)*num1=(x1*num1,y1*num1,z1*num1)
答案 A1: A2: 内部类和分部类 内部类 概念 在一个类中再申明一个类
特点 使用时要包裹者点出自己
作用 亲密关系的变现
注意 访问修饰符作用很大
实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class  Person {     public  int  age;     public  string  name;     public  Body body;     public  class  Body      {      	Arm leftArm;         Arm rightArm;         class  Arm          {                      }     } }    
调用方法 使用时要包裹者点出自己 
1 2 3 4 5 6 7 8 class  Program {     static  void  Main (string [] args     { 		Person p = new  Person();         Person.Body = new  Person.Body();     } } 
其实意义不大,分开写也无伤大雅
分部类 概念 把一个类分成几部分申明
关键字 partial
作用 分部描述一个类
增加程序的拓展性
注意 
分部类可以写在多个脚本文件中 
分部类的访问修饰符要一直 
分部类中不能有重复成员 
 
实例 1 2 3 4 5 6 7 8 9 10 11 12 13 partial  class  Student { 	public  bool  sex;     public  string  name; } partial  class  Student {     public  int  number;     public  void  Speak (string  str     {              } } 
分部方法 该方法局限性太大,了解即可
概念 将方法的申明和实现分离
特点 
不能加访问修饰符,默认私有 
只能在分部类中申明 
返回值只能是void 
可以有参数但不用,out关键字