首页 > 代码库 > 深入理解C#

深入理解C#

 

简单认识.NET框架

   (1)首先我们得知道 .NET框架具有两个主要组件:公共语言进行时CLR(Common Language Runtime)和框架类库FCL(Framework Class Library)

       配图:

              技术分享

   (2).NET的编译过程:

        配图:

              技术分享

     其中,CLR还包括通用类型系统CTS(Common Type System)和公共语言规范CLS(Common Language Specification)

   (3).NET框架核心类库及其功能

      配图:

           技术分享

        

    (4)

        C#语言要编程可以被CPU解析执行的代码需要两次编译:

         第一次编译:将C#语言通过C#编译器编译成MSIL中间代码

         第二次编译:将MSIL代码通过即时编译器(JIT)编译成CPU可以解析执行的代码,或者成为(平台专用代码)

       Java程序想要被CPU解析执行也需要两次编译:

         第一次编译:将后缀名为java的文件通过Java编译器编译成后缀名为.class(字节码)文件

         第二次编译:将.class文件通过Java虚拟机(jvm)编译成CPU可以解析的代码

    (5)面向对象

           面向对象三大特性:封装,继承和多态

          那些年我们学过的访问修饰符:

          public :任何位置,包括跨程序集

          internal:在当前程序集(项目)中都可以访问

          private:只能在当前类中访问(当前类的花括号中访问)

          protected:只能在当前类和子类中使用

    (6)变量,类和方法的命名

         骆驼命名法:第一个单词的首字母小写,后续有含义的单词首字母大写。   变量

         帕斯卡命名法:每一个单词的首字母大写    类和方法

     (7)new:代表的含义

           1.创建对象

           2.开辟空间

           3.自动调用构造函数

    (8)字段和属性的区别

           1.属性不能保存数据,真正保存数据的是字段。

           2.属性是可有可无的,字段是必须的。

           3.如果字段只是让类内部访问,那么设置成private,如果想找一个中间者,在Main方法中访问到类中的私有字段,那么属性可以是一种选择。

    (9)自动属性

          定义:当为我们不需要进行逻辑判断时可以使用自动属性。 定义自动属性在后台会自动帮我们生成一个对应数据类型的私有字段 

    (10)CLR的主要用途:

        CLR是所有.NET程序运行的环境,是所有.NET应用程序的编程基础,所有.NET受CLR监管和处理,这些操作包括进程内的应用程序加载,将IL转换为GG,

        异常处理,垃圾回收,加载程序集

深入C#数据类型

    (1)值类型和引用类型

        值类型:是在栈上存储真实的值    引用类型:在栈和堆上都开辟空间

        值类型:int  double float boolean  char byte long short  枚举(enum)  结构体(struct)

       引用类型:int[] class 接口(interface) string

    (2)结构

       定义:

         

访问修饰符  struct  结构名{            // 结构体 }例:public struct Student{      //结构体}

 

   (2)注意点:

       1.在结构中可以有字段和方法

       2.定义结构时,结构中的字段不能被赋初值

       3.可以不用new,直接定义结构的对象即可

       4.声明结构的对象后,必须给结构的成员赋初值

       5.结构体也是一种特殊的值类型

   (3)装箱和拆箱

        将值类型转换为引用类型的过程称为装箱,反之称为拆箱

       示例:

        

static void Main(String[] args){    int i=123;    oject o=i;  //装箱    i=456;   //改变i的内容   Console.WriteLine("值类型的值:{0}",i);    Console.WriteLine("引用类型的值:{0}",o); }

   (4)不同类型的参数传递
         值方式参数传递:传递数据类型是值类型,没有ref在方法中不会保留

                               传递数据类型是引用类型,没有ref在方法中会永久保留

         引用方式传递:不管有没有ref都会永久保留

    

例: class Voter{   public void Vote(SE se)   {      //人气值+1      se.Popularity++;    }}/测试相关代码SE  zhang=new SE();zhang.Age=25;zhang.Name="张梅";zhang.Gender=Gender.female;zhang.Popularity=10;//投票前MessageBox.Show(zhang.SayHi());Voter voter=new Voter();voter.Vote(zhang);  //引用类型做参数//投票后MessageBox.Show(zhang.SayHi());   

   (5)结构和类的区别
         1.结构是值类型而类是引用类型

         2.结构和另外一个结构不能继承和被继承

         3.结构没有默认构造而类有

         4.结构体没有析构函数而类有

         5.结构体可以不使用new初始化,而类不可以

使用集合组织相关数据

   (1)定义:

           集合:

         某些特定的对象集中在一起就是集合

            数组:

         可以存储相同数据类型的一堆数据的容器

    (2)集合

         集合分为泛型集合和非泛型集合

          泛型集合分为单列和双列集合  (List<T>和Dictionary<K,V>)

          非泛型集合分为单列和双列集合 (ArrayList和HashTable)

     (3)常用的方法和属性

         

 Add();   //添加 Remove();  //删除 RemobeAt(); //根据索引删除  不适用 双列集合  count  //集合存储元素的个数 Contains();  //检测元素是否存在 ContainsKey();  // ContainsValue(); Capcity //集合占用空间

     注意事项:如果删除了集合中的某一个元素,那么集合的索引会自动维护

   (4)遍历方案:

     

ArrayList list=new ArrayLIst();Student stu1=new Student(); stu1.Name="jiejie"; stu1.Age=15; list.Add(stu1);Student stu2=new Student(); stu2.Name="jiji"; stu2.Age=18; list.Add(stu2);  //foreachforeach(Student item in list){    Console.WriteLine(item.Age+"\t"+item.Name);} //forfor(int i=0;i<list.Count;i++){   Console.WriteLine((Student)list[i].Name);}

 

HashTable 遍历三种方案   HashTable table=new HashTable();第一种方式:遍历所有的Keysforeach(var item in table.Keys){    //一个item代表一个key   Console.WriteLine("key是{0}\tvalue是{1}",item,table[item]);}第二种遍历方式:遍历所有的value集合foreach(var item in table.Values){       //一个item代表一个value   Console.WriteLine("value是{0}",item);}//遍历整个tableforeach(DictionaryEntry item in table){    Console.WriteLine("key是{0}\tvalue是{1}",item.Key,item.Value);}

深入类的方法

  (1)构造函数

       方法名和类名相同,没有返回值

       注意:在C#中,当我们定义了一个类后,系统底层默认会生成一个和类名相同的无参构造,但是如果我们定义了一个带参构造,系统将不生成无参构造,但是在

              真正的开发中建议大家定义两个构造函数,一个无参构造和带参构造

    

public class SE{ public SE(){}public SE(string id,string name,int age,Gender gender,int popularity){   Id=id;   Name=name;   Age=age;   Gender=gender;   Popularity=popularity;}}

 

    (2)方法的重载

        在同一个类中,如果有多个方法方法名相同,但是参数的个数,顺序,类型不同的多个方法可以构成重载和方法的返回值类型没有关系。

      

public void Say(string name,int age){}public void Say(int age,string name){}

   (3)对象间的交互

    

//遥控器类public class RemoteControl{  //开机  public void TurnOn(Tv tv)   {     tv.Open();  //调用电视机对象的开机方法   }  //关机  public void TurnOff(Tv tv)  {    tv.TrunOff();  }   //换台  public void ChangeChannel(Tv tv)   {       Console.WriteLine("请输入频道:");       string ChannelNo=Console.ReadLine();       tv.Change(ChannelNo);   }//电视机类public class Tv{  public boolean isOn=false; //是否开机  //打开电视机  public void Open()  {   if(isOn)   {      Console.WriteLine("电视机已打开");   }   else    {       Console.WriteLine("成功打开电视机");        isOm=true;     }  }  //关机  public void TurnOff()   {     if(isOn)      {        Console.WrteLine("电视机正在关机");        isOn=false;      }     else     {       Console.WriteLine("电视机已关闭");     }   }  //换台  public void Change(string channelNo)   {     if(isOn)     {       Console.WriteLine("正在切到{0}台",channelNo);    }    }//测试Main()方法 static void Main(String[] args) {   RemoteControl controler=new RemoteControl();   Tv tv=new Tv();   //开机   controler.TurnOn(tv);    //切换频道   controler.ChangChannel(tv);   //关机   controler.TurnOff(tv);    Console.ReadLine();}

 看到这里你明白了一点了没有,回想一下上面所写的,这是一个重复的事情,一遍不行就两遍,再教你个小方法,没事的时候你就想想你学了点什么,看看自己还记得多少,忘记的就去看看自己写的,好了接下来继续吧!

   第六章 初识继承和多态

   (1)

      继承的概念是什么呢?就是一个类可以继承另一个类的属性和方法(成员)

      继承是面向对象编程中的一个非常重要的特性。

      好了,废话不多说,下面切入正题:

     1.首先我们定义一个子类,给它创建两个构造:一个无参构造和一个有参构造

      定义一个枚举类

      在定义的子类中它有自己独有的属性:

 技术分享

技术分享

     在定义的父类中的属性和构造:

 技术分享

    在Main方法中:
技术分享

    同时要注意,在调用子类的带参构造时,我们要想到调用子类构造的时候,没有使用base关键字调用父类的指定的构造,默认调用父类的无参构造.

   补充一下:

   01.base代表父类对象,如果base():调用父类的构造函数

   02.base代表的是方法调用,是不需要参数类型的

  03.base(传参顺序和父类构造一致,变量名和子类构造参数一致)

(2)在这里补充一点访问修饰符

    我们所知道的:public  private  protected

    下面我画一个图来简单的描述一下(√表示可以,×表示不可以)

                  当前类     子类     其他类(Program)
   private         √          ×        ×
   protected     √          √        ×
   public           √          √        √

    总结:我们可以清晰的明白三种访问修饰符对类成员的访问限制强度:private>protected>public

 (3)new 子类底层原理图

   我简单的用一个图来描述一下:

技术分享

    用文字描述:

      1.走到子类构造,不进入构造体
      2.转向父类,进入父类构造体执行
      3.转回子类构造,执行子类构造体
      4.转到Main,内存中构建出子类对象

  (4)继承还具有两大特性这个我们也不要忘记了,就是单根性和传递性

     单根性指的就是一个子类只有一个父类

     传递性就是只要跟父类有继承关系,就可以使用父类的属性和方法

  (5)接下来我们讲一讲多态

       1.多态是什么呢?字面上的意思就是多种形态

       用专业一点的话来说就是指同一个操作作用于不同的对象时,可以有不同的解释,产生不同的执行效果。

      我们所接触的方法重载也是多态的一种方式。

      如何实现多态呢?不要急下面我来解说

 (6)实现方法的重写

      在父类中定义的方法,用virtual关键字来定义为虚方法

     在子类中定义自己的方法,用override关键字来修饰,实现对父类的方法的重写

 (7)定义父类变量,用子类变量初始化父类变量

    下面来一个小案例:

 //创建一个Person父类 public class Person    {       public virtual void SayHello()       {            //父类特有的方法           Console.WriteLine("父类打招呼方法");       }    }//创建一个Korea子类public class Korea:Person  //在这里要注意它继承于Person类    {       public override void SayHello()       {           Console.WriteLine("金喜善打招呼方法");       }    }//创建一个Chinese类public class Chinese:Person //在这里要注意它继承于Person类    {       public override void SayHello()       {           Console.WriteLine("你好!");       }    }//创建一个American类public class American:Person   //在这里要注意它继承于Person类    {        public override void SayHello()        {            Console.WriteLine("Hello");        }    } 前面我们也学过泛型了下面我们就用泛型来存储            List<Person> list=new List<Person>();            Chinese chinese=new Chinese();            American usa=new American();            Korea korea=new Korea();            list.Add(chinese);            list.Add(usa);            list.Add(korea);

 

下面我们可以用foreach来遍历

方式一:           foreach (Person person in list)            {               person.SayHello();            }方式二:           foreach (Person person in list)            {               //方式二:不使用统一调用                if (person is Chinese)                {                   Chinese chinese= person as Chinese;                    chinese.SayHello();                }               if (person is Korea)                {                    Korea chinese= person as  Korea;                    korea.SayHello();                }               if (person is  American)                {                    American chinese= person as  American;                     american.SayHello();                }            }

 

下面我再穿插个示例:

技术分享

技术分享

技术分享

   在Main方法中调用

   看过我文章的人应该知道,在这里我们又回顾了一下,你记住了吗?

深入理解多态

   (1)里氏替换

       定义:在一个软件系统中,如果子类替换父类出现的位置,而对整个软件系统功能没有影响

     

//交通工具类public class TrafficTool{     public vartual void Run()     {         Console.WriteLine("车在行驶");     }}//地铁类public class Tube:TrafficTool{    public voerride void Run()     {       Console.WriteLine("地铁在行驶中");     }}//小汽车类public class Car:TrafficTool{   public voerride void Run()   {     Console.WriteLine("小汽车在行驶中");    }}//自行车类public class Bicycle:TrafficTool{   public override void Run()   {     Console.WriteLine("自行车在行驶中");    }}//给Employee类添加GoHome()方法:搭乘交通工具回家public class Employee{   //以父类类型作为参数   public void GoHome(TrafficTool tool)   {     Console.WriteLine("员工"+Name);     tool.Run();    }}//测试Main()方法static void Main(String[] args){   SE ai=new SE("123","艾边成",25,Gender.male,100);   SE joe=new SE("103","Joe",30,Gender.female,200);   //实例化PM对象   PM pm=new PM("890","盖茨",50,Gender.female,30);   //定义员工集合   List<Employee> list=new List<Employee>();   list.Add(ai);   list.Add(joe);   list.Add(pm);  //员工选择不同的交通工具回家:传递实际创建的子类对象  list[0].GoHome(new Bicycle());  list[1].GoHome(new Car());  list[2].GoHome(new Tube());  Console.ReadLine();}

   (2)抽象类和抽象方法

    定义:抽象方法是一个没有实现的方法,通过定义方法时增加的关键字abstract可以声明抽象方法

    语法:

      访问修饰符  abstract 返回类型 方法名();

     注意:抽象方法没有闭合的大括号,而是直接跟了一个分号;,也就是说它没有方法体。

    含有抽象方法的类必然是抽象类

    语法:

     访问修饰符  abstract class 类名{}

     

简单示例:  public abstract class TrafficTool  {     public abstract void Run();   }
 /// <summary>    /// 父类  工作类    /// </summary>   public abstract class Job    {        //抽象方法        public abstract void Show();        //工作类型        public string Type { get; set; }        //工作名称        public string Name { get; set; }        //工作描述        public string Describe { get; set; }        //无参构造        public Job()        {        }        //带参构造        public Job(string type,string name,string des)        {            this.Type = type;            this.Name = name;            this.Describe = des;        }    }
 public class Tests : Job    {        /// <summary>        /// 子类  测试类        /// </summary>            //测试类的方法        public override void Show()        {            FrmTests tt = new FrmTests();            tt.Show();            this.Num = Num;            this.BugNum = BugNum;            this.Time = Time;        }        //个数        public int Num { get; set; }        //bug数        public int BugNum { get; set; }        //时间        public string Time { get; set; }        //无参构造        public Tests()        {        }        //带参构造        public Tests(string type,string name,string des):base(type,name,des)        {        }    }

   总结:

   1.一个类用abstract修饰,就是抽象类

   2.抽象类不能实例化

   3.抽象方法不能有方法体连{}不能有

   4.抽象方法只能在抽象类中

   5.抽象方法存在的目的就是为了约束类中方法存在的形式(返回值类型和参数列表)

   6.抽象类不能是静态类和密封类

   7.抽象类中所有的抽象方法必须被子类重写,除非子类本身也是抽象类

   8.一键重写所有抽象方法的快捷键  Ctrl+.(无输入法情况下) Shift+Alt+F10

看完这章,你是不是觉得有收获?

 可扩展标记语言XML

  (1)HTML和XML

        HTML:Hyper Text Markup Language(超文本标记语言)

        XML:Extensible Markup Language(可扩展标记语言)

   (2)HTML和XML存储和展示的角度来说

       XML:侧重数据存储

       HTML:侧重数据显示

  (3)XML的注意点

      1.XML文件严格区分大小写

      2.XML文档只能有一个根节点

      3.XML文件的标签配对出现

      4.我们可以自定义XML文档中的标签 

 

深入理解C#