简介 本文记录c#学习,仅供个人参考。
基本语法 控制台方法相关 使用命名空间System中的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 27 28 29 using  System;namespace  Project {   internalk class  Program    {static  void  Main (string [] args    {       Console.WriteLine();       Console.Write();       Console.ReadLine();       Console.ReadKey();       Console.Readkey(true ).keychar       Console.Clear();              Console.SetWindowSize(width,height);       Console.SetBufferSize();                     Console.SetCursorPosition(left,top);       Console.ForegroundColor=ConsoleColor.red;       Console.BackgroundColor=ConsoleColor.white;                 Console.CursorVisible = false ;       Environment.Exit(0 ); }               }      } 
变量相关 输入#region,再按tab键自动补全,可以将#region和#endregion之间的代码折叠起来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 using  System{     namespace  Project      {         class  Program          { 		static  void  Main (string [] args          {             #region  myregion                  #endregion           }         }     }      } 
变量的区别:float浮点数申请需要末尾加一个f,不加的话默认是double类型,float有效数字保留8位,从第一个非零数字开始数起,decimal能存储25~27位的有效数字,但不建议使用,末尾加m;c#中char类型占两个字节,能用汉字赋初值,但部分生僻字不能。
类型转换 隐式和显式转换和c语言,c++没多大差别。字符串转换:类型.Parse(“字符串”);(比如说int.Parse(“123”)等于整型123)。
Convert.To类型名();转换精度更高。其他类型转string:变量类型.toString();
1 2 3 4 5 6 7 8 string  str=1. toString();str=true .toString(); Console.WriteLine("12354" +1 +true ); int  a=int .Parse("123" );char  b=char .Parse("A" );
异常捕获 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 try {           } catch {           } finally {      } 
字符串拼接 直接将字符串+字符串就能实现拼接。
或者使用string.Format(“带拼接的内容”,内容1,内容2…..);(有点类似于格式化输出)
1 2 string .Format("{0}を愛するみんなさん、{1}んにちは!、ハメドリ君だ{2}" ,"ドスケベセックス" ,"シコ" ,"ハメ" );
位运算 位与(&):连接两个数值进行位运算,将数值转为二进制。对位运算,有零为零。
位或(|):连接两个数值进行位运算,将数值转为二进制。对位运算,有一为一。
异或(^):连接两个数值进行位运算,将数值转为二进制。对位运算,相同为零,不同为一。
位取反(~):写在数值前面,零变一,一变零。
左移(<<)和右移(>>):让一个二进制的数左移或右移。
左移几位,右边多加几个零。
右移几位,右侧去掉几个数。
随机数 1 2 Random r=new  Random(); int  i=r.Next(a,b);
复杂数据类型 枚举 被命名的整型常量的集合,一般用它来表示状态,类型等等。通常和switch语句搭配使用
声明枚举:创建一个自定义的枚举类型。(枚举可以声明在namespace语句块中,也可以声明在class和struct语句中,不能在函数语句块中声明)
声明枚举变量:使用自定义的枚举类型,创建一个枚举变量。
类型转换用强制转换。用tosString();转成枚举项的名字。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 enum  E_自定义枚举名{     自定义枚举项名字,     自定义枚举项名字1 ,     ...     自定义枚举项名字n      }     eg: enum  E_player{     main,     other } E_player playertype=E_player.mian; playertype=(E_player)Enum.Parse(typeof (E_player),"枚举项名称" ); 
数组 语法:变量类型 []变量名=new 变量类型[数组大小]{这里可以赋值};(默认初始化为零)//一维数组
变量类型[,]变量名=new 变量类型[行数,列数];//二维数组
1 2 3 4 5 const  int  N=100 ;int [] a=new  int [N]{此处可以赋值};int [,] a=new  int  [3 ,3 ]{此处可以赋值};Console.WriteLine(a.GetLength(0 ); Console.WriteLine(a.GetLength(1 ); 
交错数组 语法:变量类型 [] []变量名=new 变量类型[] []
1 2 3 int [][]arr=new int[3][]{new int[3]{1,2,3},new int[2]{1,2},new int[1]{1}}; int [][]arr=new int[][]{new int[3]{1,2,3},new int[2]{1,2},new int[1]{1}}; int [][]arr={new int[3]{1,2,3},new int[2]{1,2},new int[1]{1}} 
值类型与引用类型 引用类型:string,数组,类
值类型:其它,结构体
引用类型和值类型存储的内存区域不相同,存储方式也不同。
值类型存储在栈上,系统分配,自动回收,小而快。
引用类型存储在堆空间,手动申请和释放,大而慢。
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 using  System.Diagnostics.CodeAnalysis;using  System.Runtime.InteropServices;namespace  测试程序{       class  Project      {         static  void  Main (string [] args          {             int  a = 10 ;             int  b = a;             int [] arr = new  int [] { 1 , 2 , 3 , 4  };             int [] arr2 = arr;             Console.WriteLine("a的值为{0},b的值为{1}" ,a,b);             Console.WriteLine("arr[0]的值为{0},arr2[0]的值为{1}" ,arr[0 ], arr2[0 ]);             b = 20 ;             arr2[0 ] = 9 ;             Console.WriteLine("修改之后的值为:" );             Console.WriteLine("a的值为{0},b的值为{1}" , a, b);             Console.WriteLine("arr[0]的值为{0},arr2[0]的值为{1}" , arr[0 ], arr2[0 ]);         }     } } 
string类型 虽然是引用类型,却不遵循引用类型的赋值方式,一般情况下引用类型赋值会把地址赋值给新变量,修改变量值时会直接修改地址内存内存储的值,但是string类型在赋值时会新开辟一段内存存储,使变量名指向新的地址,和值类型类似。
ref和out 可以在函数内部改变外部传入的内容,类似于c++中的引用。
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 using  System.Collections.Specialized;using  System.ComponentModel.Design;using  System.Diagnostics.CodeAnalysis;using  System.Reflection.Metadata.Ecma335;using  System.Runtime.InteropServices;namespace  测试程序{       class  Project      {         static  void  changevaule (ref  int  a         {             a = 3 ;         }         static  void  changearr (ref  int []arr         {             arr = new  int [] { 10 ,20 ,30 };         }                      static  void  Main (string [] args          {             int [] arr = new  int [] { 1 ,2 ,3 };             Console.WriteLine(arr[1 ]);             changearr(ref  arr);             Console.WriteLine(arr[1 ]);         }              } } 
变长参数和参数默认值 变长参数关键字:params
变长参数只能是函数的最后一个参数。
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 namespace  测试程序{       class  Project      {        static  int  Sum (params  int []arr         {             int  sum = 0 ;             for (int  i=0 ;i<arr.Length;i++)             {                 sum += arr[i];             }             return  sum;         }         static  int  speak (string  str="hello"          {             Console.WriteLine(str);         }                static  void  Main (string [] args          {             int  ans = Sum(1 ,2 ,3 ,4 ,5 ,6 ,7 );             Console.WriteLine(ans);             speak();         }              } } 
结构体 构造函数:函数名与结构体名相同,没有返回值,this关键字使用this.和class不相同。
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 student s1=new  student(     namespace  测试程序 {       class  Project      {        struct  student         {                         int  age;             string  name;             bool  sex;             public  student ()             {                 age = 114514 ;                 name = "田鼠浩二" ;                 sex = true ;             }                        public  void  speak ()                 {                 Console.WriteLine("我叫{0},我是{1}性,今年{2}岁" ,name,sex?'男' :'女' ,age);             }         };         static  void  Main (string [] args          {             student s1=new  student();             s1.speak();                     }              } } 
面向对象 三大特性:封装、继承、多态
封装 类和对象 类一般声明在namespace语句块中
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 class  type {                                          } class  Person {                }  Person p;     Person p2=null ;     Person p3=new  Person(); 
成员变量 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 enum  E_Animal{     dog,     cat,     bird } class  Pet {     string  name;     E_Animal type; } enum  E_SexType{     Man,     Woman } class  Person {          string  name="田鼠浩二" ;     int  age;     E_SexType sex;     Person grilFriend;          Person[] boyfriend;     Pet pet=new  Pet(); } default (类型名);
成员方法 别加static关键字
用法跟函数类似
构造、析构、垃圾回收 构造函数:在实例化对象时,会调用的用于初始化的函数,如果不写,默认存在一个无参构造函数
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 class  Person {     public  string  name;     public  int  age;                    public  Person ()     {         name="田鼠浩二" ;         age=114514 ;     }     public  Person (string  name,int  age     {                           this .name=name;         this .age=age;     }        public  Person (string  name,int  agethis ()     {                }     public  Person (string  name     {              }        public  Person (string  name,int  agethis (name )     {              }      } 
析构函数:但引用类型的堆内存被回收时,会调用该函数
//对于需要手动管理内存的语言(比如c++),需要在析构函数中做一些内存回收处理,但是c#中存在自动垃圾回收机制GC,所以几乎不会用到构造函数,在unity开发中几乎不会用到
语法:~类名()
{
}
垃圾回收机制 先放一边,之后再补
成员属性 基本概念:用于保护成员变量,为成员属性的获取和复制添加逻辑处理,解决3p的局限性,属性可以让成员变量在外部只能获取,不能修改或者是只能修改不能获取。
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 get {}set {}class  Person (){     private  string  name;     private  int  age;     private  int  money;     private  bool  sex;          public  string  Name     {         get {                                       return  name;            }         set          {                                       name=value ;          }              }     public  int  Money     {         get          {                          return  money-5 ;         }         set          {                             money=value +5 ;                      }     }          public  float  Height     {         get ;         private  set ;                                         } } Person p=new  Person(); p.Name="田鼠浩二" ; Console.Write(p.Name); 
索引器 基本概念:让对象想数组一样通过索引访问其中元素,是程序看起来更直观,更容易编写(就是专门用来访问类中数组的,类似于cpp中的运算符重载),和函数写法类似,只是把括号改成中括号
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 class  Person {     private  strint name;     private  int  age;     private  Person[] friends;          public  Person this [int  index]     {         get          {             return  friends[index];         }         set          {                          friends[index]=value ;                      }     } } Person p=new  Person(); p[0 ]=new  Person(); Console.Write(p[0 ]); 
静态成员 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 class  Test {          public  static  float  PI=3.1415926f ;          public  testInt=100 ;          public  static  float  CalcCircle (float  r     {         return  PI*r*r;     }          public  void  TestFun ()     {         Console.Write("123" );     } } Console.Write(Test.PI); 
静态类和静态构造函数(工具类) 用static修饰的类,特点:只能包含静态成员,不能被实例化。作用:将常用的静态成员写在静态类中,方便使用,静态类不能被实例化,体现了工具类的唯一性,比如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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45   static  class  TestStatic   {      public  static  int  testIndex=0 ;      public  static  void  TestFun ()      {      }      public  static  int  TestIndex      {          get ;          set ;      }  }  static  class  StaticClass    {       public  static  int  testInt = 100 ;       public  static  int  testInt2 = 200 ;       static  StaticClass ()       {           Console.WriteLine("静态构造函数" );       }   } class  Test {     public  static  int  testInt=200 ;          static  Test ()     {         Console.WriteLine("静态构造" );     }          public  Test ()     {         Console.WriteLine("普通构造" );      } } 
拓展方法 基本概念:为现有的 非静态 变量类型 添加新方法,作用:提升程序拓展性,不需要在对象中重新写方法,不需要继承来添加方法,为别人封装的类型写额外的方法。
特点:一定是写在静态类中,一定是一个静态函数,第一个参数为拓展目标,第一个参数用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 35 36 37 38 39 40 41 42 43 44 45 static  class  Tools {                    public  static  void  SpeakValue (this  int  value      {         Console.WriteLine("田鼠浩二为int拓展的方法" +value );     }          public  static  Fun3 (this  Test t     {         Console.WriteLine("为Test拓展的方法" );     } } int  i=10 ;i.SpeakValue(); class  Test {     public  int  i=10 ;          public  void  Fun1 ()     {         Console.Write("123" );     }          public  void  Fun2 ()     {        Console.WriteLine("456" );     } } Test t=new  Test(); t.Fun3(); 
运算符重载 概念:让自定义类和结构体能够使用运算符
使用关键字 operator
特点:一定是一个公共的静态方法,返回值卸载operator前,逻辑处理自定义
作用:让自定义类和结构体对象可以进行运算,条件运算符需要成对实现,一个符号可以多个重载,不能使用ref和out(相当于自定义一种运算方式)
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 public  static  返回类型 operator  运算符(参数列表)         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  value )         {             Point p=new  Point();             p.x=p1.x+value ;             p.y=p1.y+value ;             return  p;         }     } Point p1=new  Point(); p1.x=1 ; p1.y=1 ; Point p2=new  Point(); p2.x=2 ; p2.y=2 ; Point p3=p1+p2; Point p4=p3+2 ; 
可重载的运算符:算术运算符,逻辑运算符(只有非!),位运算符,条件运算符(需要成对实现,重载了大于就要重载小于)
不可重载的运算符:逻辑与,逻辑或,索引符,强转运算符,特殊运算符,点,三目运算符,赋值符号
内部类和分布类 内部类:一个类中再申明一个类
特点:使用时要用包裹者点出自己
作用:亲密关系的变现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class  Person {     public  int  age;     public  string  name;     public  Body body;     public  class  Body      {         Arm leftArm;         Arm rightArm;         class  Arm          {                      }     } } Person p=new  Person(); Person.Body body=new  Person.Body(); Person.Arm 
分布类:把一个类分成几部分申明
关键字:partial
作用:分布描述一个类,增加程序的拓展性。(可以写在多个脚本文件中,分布类的访问修饰符要一致,不能有重复成员)其实就是把一个类分成好几个语句块中写。
分部方法:将方法的申明和实现分离
特点:不能加访问修饰符(默认私有),只能在分布类中申明,返回值只能是void,可以有参数但不用,out关键字,局限性大,了解即可。
继承 继承的基本概念 基本概念:一个类a继承一个类b,类a会继承类b的所有成员,a类将拥有类b的所有特征和行为。
被继承的类叫做父类、基类、超类。继承的类叫做子类、派生类。子类可以有自己的特征和行为。
特点:单根性 子类只能有一个父亲。传递性 子类可以间接继承父类的父亲(类似于树状结构)
c#中允许父类和子类同名的成员,但不建议使用(会覆盖父类的同名成员)。
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 class  Teacher {          public  string  name;          protected  int  number;          public  void  SpeakName ()     {         Console.WriteLine(name);     } } Class TeachingTeacher:Teacher {          public  string  subject;          public  void  SpeakSubject ()     {         Console.WriteLine(subject+"老师" );     }      } TeachingTeacher tt=new  TeachingTeacher(); tt.name="田鼠浩二" ; tt.number=1 ; tt.SpeakName(); tt.subject="unity" ; tt.SpeakSubject(); 
里氏替换原则(LSP)(面向对象七大原则之一) 基本概念:任何父类出现的地方,子类都可以替代。父类容器装子类对象,因为子类包含了父类的全部内容
作用:方便进行对象存储和管理
is:判断一个对象是否是指定类对象,返回值是bool,是为真,不是为假。
as:将一个对象转换为指定类对象,返回值为指定类对象,失败返回null
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 class  GameObject  {  }  class  Player  : GameObject   {      public  void  PlayerAtk ()      {          Console.WriteLine("玩家攻击" );      }  }  class  Monster  : GameObject   {      public  void  MonsterAtk ()      {          Console.WriteLine("怪物攻击" );      }  }  class  Boss  : GameObject   {      public  void  BossAtk ()      {          Console.WriteLine("Boss攻击" );      }  }    GameObject player = new  Player();  GameObject monster = new  Monster();  GameObject boss = new  Boss();  GameObject[] objects = new  GameObject[] { new  Player,new  Monster,new  Boss}; if (player is  Player){      } Player p=player as  Player; Player p=monster as  Player; 
继承中的构造函数 特点:当申明一个子类对象时,先执行父类的构造函数,再执行子类的构造函数
父类的无参构造函数很重要。子类可以通过base关键字代表父类,调用父类构造函数
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 class  Father {     public  Father ()     {              }          public  Father (int  i     {         Console.WriteLine("Father构造" );     } } class  Son :Father {     public  Son (int  ibase (i )     {         	     }          public  Son (int  i,string  strthis (i )     {              }      } 
万物之父和装箱拆箱 关键字:object,概念:是所有类型的父类,是一个类(引用类型),作用:可以利用里氏替换原则,用object容器装所有对象,可以用来表示不确定类型,作为函数参数类型。
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 class  Father {      } class  Son :Father {     public  void  Speak ()     {              } } Father f=new  Son(); if (f is  Son){     (f as  Son).Speak(); } object  o=new  Son();if (o is  Son){     (o as  Son).Speak(); } object  o2=1f ;float  f1=(float )o2;object  str="123123" ;string  str2=str as  string ;object  arr=new  int [10 ];int  []ar=arr as  int [];object  v=3 ;int  inValue=(int )v;static  void  TestFun (params  int [] array{      } 
密封类(不是很重要) 概念:使用sealed密封关键字修饰的类
作用:让类无法再被继承
1 2 3 4 5 6 7 8 9 10 11 12 class  Father {      } sealed  class  Son :Father { } 
多态 多态vob 多态:多种状态,让继承同一父类的子类们,在执行相同方法时有不同的表现,解决的问题:让同一个对象有唯一行为的特征。
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  Father {     public  void  SpeakName ()     {              } } class  Son :Father {     public  new  void  SpeakName ()     {              } } Father f=new  Son(); f.SpeakName(); (f as  Son).SpeakName(); class  GameObject {     public  string  name;          public  GameObject (string  name     {         this .name=name;     }          public  virtual  void  Atk ()     {         Console.WriteLine("游戏对象进行攻击" );     } } class  Player :GameObject {     public  Player (string  namebase (name )     {              }          public  override  void  Atk ()     {                           base .Atk();         console.WriteLine("让玩家对象进行攻击" );     } } 
即使使用了父类容器装载子类的实例化对象,但是通过重写之后可以直接使用子类的同名函数,不需要通过as进行转化了
抽象类和抽象方法 抽象类
概念:被抽象关键字abstract修饰的类,特点:不能被实例化,可以包含抽象方法,继承抽象类必须重写其抽象方法
抽象函数
又叫纯虚方法,用abstract修饰的方法,特点:只能在抽象类中申明,没有方法体,不能是私有的,继承后必须要实现,用override重写
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 abstract  class  Thing {          public  string  name;           } class  Water :Thing {      } Thing t=new  Water(); abstract  class  Fruits { 	public  string  name;          public  abstract  void  Bad ()          public  virtual  void  Test ()     {              } } class  Apple :Fruits {     public  override  void  Bad ()     {              }          public  override  void  Test ()     {              } } class  SuperApple :Apple {          public  override  void  Bad ()     {              }          public  override  void  Test ()     {              } } 
接口 概念:是行为的抽象规范,是一种自定义类型,关键字:interface
接口申明的规范:不包含成员变量,只包含方法、属性、索引器、事件,成员不能被实现,成员可以不用写访问修饰符,不能是私有的,接口不能继承类,但是可以继承另一个接口
接口的使用规范:类可以继承多个接口,类继承接口后,必许实现接口中的所有成员
特点:和类的声明类似,接口是用来继承的,接口不能被实例化,但是可以作为容器存储对象
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 interface  IFly { 	void  Fly ()              string  Nmae     {         get ;         set ;     }          int  this [int  index]     {         get ;         set ;     }          event  Action doSomething     {              } } class  Animal {      } class  Person :Animal ,IFly {    public  virtual  void  Fly ()     {              }        public  string  Name     {         get ;         set ;     }          public  int  this  [int  index]     {         get          {             return  0 ;         }         set          {                      }     }          public  event  Action doSomething;    } IFly f=new  Person(); 
接口的主要作用:类似于行为的多态,可以为不同种对象但是又有相同行为的对象提供方法
接口可以继承接口,不需要去实现,待类继承接口后,类自己去实现所有内容。
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 interface  IAtk {     void  Atk () } interface  ISuperAtk {     void  Atk () } class  Player :IAtk ,ISuperAtk {          public  void  IAtk.Atk()     {              }          public  void  ISuperAtk ()     {              } } 
抽象类和接口的区别 抽象类和抽象方法:abstract修饰的类和方法,抽象类不能实例化,抽象方法只能在抽象类中申明,是纯虚方法,必须在子类中实现。
接口:interface 自定义类型,是行为的抽象,不包含成员变量,仅包含方法,属性,索引器,事件,成员都不能是实现,建议不写访问修饰符,默认public
相同点:都可以被继承,都不能直接实例化,都可以包含方法申明,子类必须实现未实现的方法,都遵循里氏替换原则。
不同点:抽象类中可以有构造函数,接口中不能,抽象类只能被单一继承,接口可以被继承多个,抽象类中可以有成员变量,接口中不能,抽象类中可以申明成员方法,虚方法,抽象方法,静态方法;接口只能申明没有实现的抽象方法,抽象类方法可以使用访问修饰符,接口中建议不写,默认public
使用:表示对象的用抽象类,表示行为拓展的用接口,不同对象拥有的共同行为,我们往往可以使用接口来实现
密封函数(不是很重要) 概念:用密封关键字sealed修饰的重写函数,作用:让虚方法或者抽象方法之后不能再被重写,特点:和override一起出现
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 abstract  class  Animal {     public  string  name;     public  abstract  void  Eat ()     public  virtual  void  Speak ()     {         Console.WriteLine("叫" );     } } class  WhitePerson :Person {     public  override  void  Eat ()     {     base .Eat();         }          public  override  void  Speak ()     {         base .Speak();     }           } class  Person :Animal {     public  sealed  override  void  Eat ()     {              }     public  override  void  Speak ()     {              } } 
命名空间 概念:命名空间是用来组织和重用代码的,作用:就像是一个工具包,类就像是一件件的工具,都是申明在命名空间里的
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 namespace  命名空间名{           } namespace  MyGame {     class  GameObject      {              } } namespace  MyGame {     class  Player :GameObject      {              } } using  命名空间名          
万物之父中的方法 object中的静态方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class  Test { } Test t=new  Test(); Test t2=new  Test(); Object.Equals(t,t2); Object.referenceEquals(t2,t) 
object中的成员方法
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 Test t=new  Test(); Type type =t.GetType(); class  Test {     public  int  i=1 ;     public  Test2 t2=new  Test();     public  Test clone ()     {         return  MemberwiseClone() as  Test;     } } class  Test2 {     public  int  i=2 ; } Test t2=t.Clone(); Console.WriteLine(t.i); Console.WriteLine(t.t2.i); Console.WriteLine(t2.i); Console.WriteLine(t2.t2.i); t2.i=20 ; t2.t2.i=21 ; 
 object中的虚方法
string类型 字符串本质是一个char数组
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 string  str="田鼠浩二" ;Console.WriteLine(str[0 ]); char []chars=str.ToCharArray();Console.WriteLine(chars[1 ]); for (int  i=0 ;i<str.Length;i++){     Console.WriteLine(str[i]); } str=string .Format("{0}{1}" ,1 ,3333 ); console.WriteLine(str); str="我是田鼠浩二" ; str.indexOf("田" ); int  index=str.IndexOf("吊" );Console.WriteLine(index); str="我是田鼠浩二田鼠浩二" ; index=str.LastIndexOf("田鼠浩二" ); str="我是田鼠浩二田鼠浩二" ; str=str.Remove(4 ); Console.WriteLine(str); str=str.Remove(1 ,1 ); str="我是田鼠浩二田鼠浩二" ; str=str.Replace("田鼠浩二" ,"田所浩二" ); Console.WriteLine(str); str="naohdflkdsafs" ; str=str.ToUpper(); Console.WriteLine(str); str=str.ToLower(); Console.WriteLine(str); str="田鼠浩二" ; str.Substring(2 ); Console.WriteLine(str); str=str.Substring(2 ,3 ); Console.WriteLine(str); str=str.Substring(0 ,1 ); Console.WriteLine(str); str="1,2,3,4,5,6,7,8" ; string []strs=str.Split(',' );for (int  i=0 ;i<strs.Length;i++){     Console.WriteLine(strs[i]); } 
StringBuilder 优势是可以预先分配内存,避免过度浪费,其他和string差不多
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 StringBuilder str=new  StringBuilder("123123123" ); Console.WriteLine(str); Console.WriteLine(str.Capacity); Console.writeLine(str.Length); str.Append("3333" ); str.AppendFormat("{0}{1}" ,100 ,200 ); str.Insert(0 ,"田鼠浩二" ); str.Remove(0 ,10 ); str.Clear(); Console.WriteLine(str[0 )];                    str[0 ]='A' ; str.Replace("1" ,"田" );                    str.Clear(); str.Append("123" );                    str.Equals("123" ) 
类和结构体的区别 类是引用类型,结构体是值类型。都可以用来形容对象,结构体没有继承和多态的特性,结构体不具备继承的特性,不能用protected保护访问修饰符。结构体成员变量不能指定初始值,结构体不能申明无参的构造函数,结构体申明有参构造函数后,无参的不会被顶掉,结构体不能申明析构函数,结构体不能被静态static修饰,类可以,结构体不能在自己内部申明和自己一样的结构体变量,类可以。
结构体可以继承接口,因为接口是行为的抽象。
选择:想要用继承和多态是直接用类(比如玩家,怪物等),对象是数据集合时优先考虑结构体(比如位置,坐标等)
从值类型和引用类型赋值时的区别考虑,比如经常被赋值传递的对象,并且改变赋值对象,原对象不想跟着变化时,用结构体,比如坐标,向量,旋转等。
多脚本文件 新建脚本文件:
一般一个类一个脚本,一个结构体一个脚本,一个接口一个脚本,枚举在特殊情况下也可以一个脚本。
在文件夹中新建脚本文件:
可以将相同类型的脚本放在一个文件夹中
c#脚本文件后缀是.cs  c#解决方案中的一些重要文件夹 如bin 解决方案资源管理器窗口 工程右键 点添加
文件中新建脚本文件需要注意命名空间改变
UML类图 统一建模语言(Unified Modeling Language,UML)是一种为面向对象系统的产品进行说明、可视化和编制文档的一种标准语言,是非专利的第三代建模和规约语言。UML是面向对象设计的建模工具,独立于任何程序设计语言。
使用一些高级的UML可视化软件,不用写代码,通过做一些图表相关内容就可以直接生成代码,在其基础上进行开发。他的最终目标是直接能通过图形就把业务逻辑完成
UML类图是UML其中很小的一部分,可以帮助我们理清对象间关系
面向对象七大原则 单一职责原则(SRP) 类被修改的几率很大,因此应该专注于单一的功能。如果把多个功能放在同一个类中,功能之间就形成了关联,改变其中一个功能,可能终止另一个功能。例如程序,策划,美术三个工种是三个类,应该各司其职,只做自己的工作
开闭原则(OCP) 对拓展开发,对修改关闭。拓展开放:模块的行为可以被拓展从而满足新的需求  拓展关闭:不允许修改模块的源代码(或者尽量使修改最小化)继承就是最典型的开闭原则的体现,可以通过添加子类和重写父类的方法来实现。
里氏替换原则(LSP) 任何父类出现的地方,子类都可以替代。
依赖倒转原则(DIP) 要依赖与抽象,不要依赖于具体的实现。
迪米特原则(LoP) 最少知识原则,一个对象应当对其它对象尽可能少的了解,不要和陌生人说话。
一个对象的成员,要尽可能少的直接和其他类建立关系,降低耦合性
接口分离原则(ISP) 不应该强迫别人依赖他们不需要使用的方法,一个接口不需要提供太多的行为,一个接口应该尽量只提供一个对外的功能,让别人去选择需要实现什么样的行为,而不是把所有行为封装到一个接口里。
合成复用原则(CRP) 尽量使用对象组合,而不是继承来达到复用的目的,继承关系是强耦合,组合关系是低耦合,例如脸是眼睛、鼻子、嘴巴、耳朵的组合,而不是继承,角色和装备也是组合。
数据结构 ArrayList 本质是一个object类型的数组,在system.collections命名空间里。
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 ArrayList array=new  ArrayList(); array.Add(); ArrayList array2=new  ArrayList(); array.AddRange(array2); array.Insert(1 ,"1234565" ); array.Remove(); array.RemoveAt(2 ); array[0 ]; arr.Contains()      array.IndexOf(); array.LastIndexOf(); array[0 ]="000" ; array.Count array.capacity      for (int  i=0 ;i<array,Count;i++{      Console.WriteLine(array[i]); } foreach (object  item in  array){     Console.WriteLine(item); } int  i=1 ;array[0 ]=i; i=(int )array[0 ]; 
Stack 栈,先进后出,本质也是一个object数组,只不过封装了特殊的存储规则
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 Stack stack=new  Stack(); stack.Push(); stack.Pop(); stack.Peek(); stack.Contains(); stack.Clear(); stack.Count foreach (object  temp in  stack){     Console.WriteLine(temp); } object []array=stack.ToArray();for (int  i=0 ;i<array.Length;i++){      } while (stack.Count>0 ){     object  o=stack.Pop();     Console.WriteLine(o); } 
Queue 队列,先进先出,本质也是一个object数组,只不过封装了特殊的存储规则
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 Queue queue=new  Queue(); queue.Enqueue(); queue.Dequeue(); queue.Peek(); if (queue.Contains()){      } queue.Clear(); queue.Count; foreach (object  item in  queue){      } 
HashTable 哈希表,也就是散列表,使用键来访问集合中的元素,就是c++中的map
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 Hashtable hashtable=new  Hashtable(); hashtable.Add(1 ,"123" ); hashtable.Add("123" ,2 ); hashtable.Add(true ,true ); hashtable.Remove(); hashtable.Clear(); hashtable[键]; hashtable.Contain(键); hashtable.ContainKey(键); hashtable.ContainValue(值); hashtable.Count; foreach (object  item in  hashtable.Keys){     Console.WriteLine(item);     Console.writeLine(hashtable[item]); } foreach (object  item in  hashtable.Values){     Console.WriteLine(item); } foreach (DictionaryEntry object  item in  hashtable){     Console.WriteLine(item.key,item.Value); } IDictionaryEnumerator myEnumerator= hashtable.GetEumerator(); bool  flag=myEnumerator.MoveNext();while (flag){     Console.WriteLine(myEnumerator.Key,myEnumerator,Value); } 
泛型 概念:实现了类型参数化,达到代码重用的目的,相当于类型占位符,定义类或者方法时使用替代符代表变量类型,当真正使用类或者方法时再具体指定类型。(c++中vector类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class  类名<泛型占位字母>interface  接口名<泛型占位字母>函数名<泛型占位字母>(参数列表)  class  TestClass <T >{     public  T value ; } TestClass<int > t=new  TestClass<int >(); t.value =10 ; Console.WriteLine(t.value ); TestClass<string >t2=new  TestClass<string >(); 
泛型约束 概念:让泛型有一定的限制,关键字:where
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 class  Test1 <T >where  T :struct {     public  T value ;          public  void  TextFun <K >(K,k )where  K:struct      {              } } class  Test2 <T >where  T :class {     public  T value ;          public  void  TestFun <K >(K,v ) where  K:class                   public  Test2 (int  a     {              } } class  Test3 <T >where  T :new (){     public  T value ;          public  void  TestFun (K,k )where  K:new ()     {              } } void  main (){     Test1<object >t1=new  Test1<object >();     Test1<int >t2=new  Test2<int >();          Test3<Test1>t3=new  Test3<Test1>();     Test3<Test2>t4=new  Test3<Test2>(); } 
泛型数据结构类 List 是c#中封装好的一个类,是可变类型的泛型数组,List帮助我们实现了许多方法,类似于cpp中的vector
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 List<int >list=new  List<int >(); List<string >list2=new  List<bool >(); list.Add(); list.Remove(); list.RemoveAt(); list[0 ]; list.IndexOf(); list.LastIndexOf(); list.Insert(); list.Count; list.Capacity; foreach (int  temp in  list){     Console.WriteLine(temp); } 
Dictionary 字典,有泛型的hashtable,就是hashtable,尽量用这个,别用非泛型类型,这个类型和hashtable的使用方法是一样的,这里笔者不多说了,和hashtable区别:找不到键的话直接报错,用TryGetValue方法不会报错
LinkedList 封装好的类,是一个泛型的双向链表
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 LinkedList<int >linkedlist=new  LinkedList<int >(); linkedlist.AddLast(); linkedlist.AddFirst(); LinkedListNode<int >n=linkedlist.Find(20 ); linkedlist.AddAfter(n,12 ); AddBefore() linkedlist.RemoveFirst(); linkedlist.RemoveLast(); linkedlist.Remove(具体元素); linkedlist.Clear(); LinkedListNode<int >first=linkedlist.First; LinkedListNode<int >last=linkedlist.Last; LinkedListNode<int >node=linkedlist.Find(具体元素); linkedlist.Contains(元素); node.value =新值; foreach (int  item in  linkedlist){     Console.WriteLine(item); } 
泛型栈和队列 和c++中的一样
委托 概念:委托是函数的容器,可以理解为表示函数的变量类型,用来存储传递函数,委托的本质是一个类,用来定义函数的类型,不同的函数必须对应和各自“格式”一致的委托。(类似于函数指针),可以作为某些触发机制,在前置条件完成后,将委托中的函数(行为)全部执行
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 delegate  void  MyFun ()delegate  int  MyFun2 (int  astatic  void  Fun ()    {        Console.WriteLine("你好" );      } static  int  Fun2 (int  value {     return  value ; } Main() {          MyFun f=new  MyFun(Fun);          f,Invoke();               MyFun f2=Fun;          f2();             Test t=new  Test();          t.TestFun(Fun,Fun2); } class  Test {     public  MyFun fun;     public  MyFun2 fun2;          public  void  TestFun (MyFun fun,MyFun fun2 )     {                  int  i=1 ;         i+=2 ;         i+=2 ;         fun();         fun2(i);           this .fun=fun;         this .fun2=fun2;     }               public  void  RemoveFun (MyFun fun,MyFun2 fun2 ) {     this .fun-=fun;     this .fun2-=fun2; } } MyFun ff=null ; ff+=Fun; ff+=Fun; ff(); ff=null ; if (ff!=null ){     ff(); } 
系统定义好的委托(使用系统自带的委托需要引用system):
1 2 3 4 public  delegate  void  Action ()public  delegate   TResult Func <out  TResult >()public  delegate  void  Action <in  T >(T obj )public  delegate  TResult Func <in  T ,out  TResult >(T arg )
回调机制(补充) 回调是一种编程模式,其中一个函数作为参数传递给另一个函数,并在特定条件满足或者事件发生时调用。
一般可以使用委托实现。因为在回调中通常只存在一个订阅者,所以强调的是完成时调用我的单向通知,
调用者是知道被调用者的。
观察者模式(补充) 观察者模式是一种行为设计模式,定义了对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象多会自动收到通知并更新。一般可以使用事件实现。因为观察者模式中通常有多个订阅者,强调“‘某事发生了”的广播通知,让多个订阅者知道事件的发生
事件 事件是基于委托的存在,事件是委托的安全包裹,让委托的使用更具有安全性,事件是一种特殊的变量类型,是特殊封装的委托。
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 class  Test {       public  Action myFun;       public  event  Action myEvent;          public  Test ()     {                  myFun=TestFun;         myEvent=TestFun;         myEvent+=TestFun;     }          public  void  TestFun ()     {              } }  class  Project   {          static  void  Main (string [] args       {          Test t = new  Test();          t.myFun = null ;          t.myEvent = null ;                    t.myFun();                    t.myEvent();      }              } 
空条件运算符(补充) 在调用委托和事件时通常要判断是否为空,具体可写一个条件语句判断,这里可以用更加简洁的空条件运算符(?.)
1 2 3 4 5 6 if (event !=null ){     event (); } event ?.();
匿名函数 概念:没有名字的函数,主要是配合委托和事件进行使用,脱离委托和事件是不会使用匿名函数的
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 	 Action a = delegate () {     Console.WriteLine("匿名函数逻辑" ); }; a(); Action<int ,string > b = delegate (int  a,string  b) {     Console.WriteLine(a);     Console.WriteLine(b); }; b(100 ,"123" ); Func<string > c=  delegate  () {     return  "12345" ; } Console.WriteLine(c()); Test t=new  Test(); t.Dosomething(100 ,delegate (){                }); t.GetFun()(); class  Test {     public  Action action;          public  void  Dosomething (int  a,Action fun     {         Console.WriteLine(a);         fun();     }          public  Action GetFun ()     {         return  delegate ()         {             Console.WriteLine("函数内部返回的一个匿名函数逻辑" );         };     } } 
lambda表达式 可以将lambda表达式理解为匿名函数的简写,他除了写法不同外,使用上和你匿名函数一样,都是和委托和事件配合使用的
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      Action a = ()=> {     Console.WriteLine("  " ); }; a(); Action<int > a =(int  b)=> {      }; a2(100 ); Action<int >a3= (value )=> {      } Func<string ,int >a4=(value )=> {     return  1 ; } class  Test {     public  event  Action action;          public  Test ()     {         int  value =30 ;                  action=()=>         {          Console.WriteLine(value );         };     } } 
List排序 List自带的排序方法
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 List<int >list=new  List<int >(); list.Add(2 ); list.Add(3 ); list.Add(1 ); list.Sort(); class  Item :IComparable <Item >{     public  int  money;          public  Item (int  money     {         this .money=money;     }          public  int  Comparable (Item other )     {                                                                                 if (this .money>other.money)         {             return  1 ;         }                           else           {             return  -1 ;         }     } } List<Item>itemList=new  List<Item>(); itemList.Add(new  Item(34 )); itemList.Add(new  Item(12 )); itemList.Add(new  Item(23 )); itemList.Add(new  Item(90 )); itemList.Add(new  Item(89 )); itemList.Sort(); class  ShopItem {     public  int  id;     public  ShopItem (int  id     {         this .id=id;     } } List<ShopItem>shopItems=new  List<ShopItem>(); shopItems.Add(new  ShopItem(3 )); shopItems.Add(new  ShopItem(2 )); shopItems.Add(new  ShopItem(1 )); shopItems.Add(new  ShopItem(6 )); shopItems.Add(new  ShopItem(9 )); static  int  SortShopItem (ShopItem a,ShopItem b ){                    if (a.id>b.id)     {         return  1 ;     }          else  return  -1 ;     return  0 ; } ShopItems.Sort((a,b)=>{return  a.id-b.id};); shopItems.Sort(SortShopItem); 
协变逆变 概念:协变:和谐的变化。因为里氏替换原则,父类可以装载子类,比如string变成object。
逆变:不正常的变化。比如object变成string。
协变和逆变是用来修饰泛型的
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 delegate  T TestOut <out  T >()delegate  void  TestIn <in  T >(T t )delegate  T TestOut <out  T >()delegate  void  TestIn <in  T >(T t )class  Father {      } class  Son :Father {      } Main() {                    TestOut<Son>os=()=>     {       reutrn new  Son () ;       };          TestOut<Father>of=os;     Father f=of();              TestIn<Father>iF=(value )=>    {            };          TestIn<Son>iS=iF;     iS(new  Son())          } 
多线程 进程(process)是计算机的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。打开一次应用程序就是在操作系统中开启了一个进程,进程之间可以相互独立运行,互不干扰,也可以相互访问,操作。
线程,操作系统中能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位,一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程(简单理解:就是代码从上到下运行的一条管道)
多线程
我们可以通过代码开启新的线程。
同时运行代码的多条管道,就叫多线程。
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 Thread t=new  Thread(NewThreadLogic); t.Start(); t.IsBackGround=true ; t.ABort(); t=null ; static  void  NewThreadLogic (){     while (true )     { 	     }      } Thread.Sleep(); 
预处理器指令 编译器:编译器是一种翻译程序,它用于将源语言程序翻译为目标语言程序
源语言程序:某种程序设计语言写成的,比如c#、c++等语言写成的程序
目标语言程序:二进制数表示的伪机器代码写的程序
预处理器指令:知道编译器在实际编译开始之前对信息进行预处理
预处理器都是以#开始
预处理器指令不是语句,所以他们不以分号结束,目前我们经常用到的折叠代码块就是预处理器指令
反射 程序集:是经由编译器编译得到的,供进一步编译执行的那个中间产物,在windows系统中,他一般表现为后缀为:.dll(代码库文件),或者是.exe(可执行文件)的格式。
程序集就是我们写的一个代码集合,我们现在的所有代码最终都会被编译器翻译为一个程序集供别人使用
元数据: 用来描述数据的数据。程序中的类、变量等等信息就是程序的元数据,保存在数据集中
反射:程序在运行时可以查看其它程序集或者自身的元数据。一个运行的程序查看本身或者其他程序的元数据的行为就叫做反射。就是在程序运行时,通过反射可以得到其他程序及或者他们自己程序集代码的各种信息。类、函数、变量、对象等等。实例化他们,执行他们。操作他们
反射可以在程序编译后获得信息,所以它提高了程序的拓展性和灵活性。
程序运行时得到所有元数据,包括元数据的特性。
程序运行时,实例化对象,操作对象
程序运行时创建新对象,用这些对象执行任务
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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 class  Test {     private  int  i=1 ;     public  int  j=0 ;     public  string  str="123" ;          public  Test ()     {              }          public  Test (int  i     {         this .i=i;     }          public  Test (int  i,string  strthis (i )     {         this .str=str;     }          public  void  Speak ()     {              } } int  a=32 ;Type type=a.GetType(); Console.Write(Type); Type type2=typeof (int ); Console.Write(type2); Type type3=Type.GetType("System.Int32" ); Console.WriteLine(type3); Console.WriteLine(type1.Assembly);f Type t=typeof (Test); MemberInfo[]infos=t.GetMembers(); for (int  i=0 ;i<infos.Length;i++){     Console.WriteLine(infos[i]); } ConstructorInfo[] ctors=t.GetConstructors(); for (int  i=0 ;i<ctors.Length;i++){     Console.WriteLine(ctors[i]); } ConstructInfo info=info=t.GetConstructor(new  Type[0 ]); Test obj=info.Invoke(null ) as  Test; ConstructInfo info2=t.GetConstructor(new  Type[] {typeof (int )}); obj=info2.Invoke(new  object []{2 })as  Test; Console.WriteLine(obj.str); FieldInfo[] fieldInfos=t.GetFields(); for (int  i=0 ;i<fieldinfos.Length;i++){     Console.WriteLine(fieldinfos[i]); } FieldInfo infoJ=t.GetField("j" ); Console.WriteLine(infoJ); Test test=new  Test(); test.j=99 ; test.str="2222;  //通过反射 获取对象的某个变量的值 Console.WriteLine(infoJ.GetValue(test)); //通过反射 设置指定对象的某个变量的值 infoJ.SetValue(test,100); Console.WriteLine(infoJ.GetValue(Test)); //获取类的公共成员方法 //通过Type类中的GetMethod方法,得到类中的方法 //MethodInfo是方法的反射信息 Type strType=typeof(string); //如果存在方法重载 用Type数组表示参数类型 MethodInfo[] methods=strType.GetMethods(); for(int i=0;i<methods.Length;i++) {     Console.WriteLine(methods[i]); } //Activator //用于快速实例化对象的类 //用于将Type对象快捷实例化为对象 //先得到Type //然后 快速实例化一个对象 Type testType =typeof(Test); //无参构造 Test testObj=Activator.CreateInstace(testType) as Test; Console.WriteLine(testObj.str); //有参数构造 testObj=Activator.CreateInstance(testType,99)as Test;//调用一个参数的构造函数 Console.WriteLine(testObj.j); testObj=Activator.CreateInstance(testType,88," 14566 ")as Test; Console.WriteLine(testObj.j,testObj.str); //Assembly //程序集类 //主要用来加载其他程序集,加载后 //才能用Type来使用其他程序集中的信息 //比如想要使用不是自己程序集中的内容,首先要加载程序集 //比如 dll文件(库文件) //简单地把库文件看成一种代码仓库,他提供给使用者一些可以直接拿来用的变量,函数或类 //三种加载程序集的函数 //一般用来加载在同一文件下的其他程序集 //Assembly assembly=Assembly.Load(" 程序集名称");(同一工程) //Assembly assembly2=Assembly.LoadFrom(" 包含程序集清单的文件的名称或路径"); //Assembly assembly3=Assembly.LoadFile(" 要加载文件的完全限定路径"); //先加载一个指定程序集 Assembly assmbly=Assembly.LoadFrom(" 略"); Type[] types=assembly.GetTypes(); for(int i=0;i<types.Length;i++) {     Console.WriteLine(types[i]); } //之后再加载程序集中的一个类对象才能使用反射 Type icon=assembly.GetType(" 略"); MemberInfo[] members=icon.GetMembers(); for(int i=0;i<members.Length;i++) {     Console.WriteLine(Members[i]); } //通过反射实例化icon对象 //略 
特性 特性是一种允许我们想程序的程序集添加元数据的语言结构,是用于保存程序结构信息的某种特殊类型的类。特性提供功能强大的方法以声明信息与c#代码相关联,特性与程序实体相关后即可在运行时使用反射查询特性信息。特性的目的是告诉编译器把程序结构的某组元数据嵌入程序集中。可以放置在几乎所有的声明中。特性本质是一个类,可以利用特性类为元数据添加额外信息,之后可以用反射来获取这些额外信息。
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 class  MyCustomAttribute :Attribute {         	public  string  info;          public  MyCustomAttribute (string  info     {         this .info=info;     }          public  void  TestFun ()     {         Console.WriteLine("特性的方法" );     } }     [MyCustom("田鼠浩二" ) ] class  MyClass {     [MyCustom("这是一个成员变量" ) ]     public  int  value ;          [MuCustom("计算加法的函数" ) ]     public  void  TestFun ([MyCustom("函数参数"  )]int  a)     {              } } class  Program {     static  void  Main (string  [] args      {         Console.WriteLine("特性" );                  Myclass mc=new  MyClass();         Type t=mc.GetType();         t=typeof (MyClass);         t=Type.GetType("" );                                                      if (t.IsDefind(typeof (MyCustomAttribute),false ))         {             Console.WriteLine("该类型应用了MyCustom特性" );         }                          object []array= t.getCustomAttributes(true );         for (int  i=0 ;i<array.Length;i++)         {             if (array[i] is  MyCustomAttribute)             {               console.WriteLine((array[i] as  MyCustomAttribute).info);                 (array[i] as  MyCustomAttribute).TestFun();                              }         }     } }