zoukankan      html  css  js  c++  java
  • .NET基础笔记(C#)

         闲着没事就把以前学习时的笔记拿出来整理了一下,个人感觉有点用,就想拿出来跟园友共享一下。有些基础性的内容比如基本概念、语法什么的就不发了。

    内容:1、构造方法(函数) 2、继承   3、访问修饰符  4、静态和非静态  5、隐藏基类方法  6、重写基类方法  7、抽象方法  8、接口  9、多态和接口  10、值类型与引用类型  11、ref和out  12、类型转换  13、异常处理  14、string字符串处理  15、string常用方法  16、StringBulider  17、File类读取文件  18、文本高亮 19、泛型集合List<T>和Dictionary<TKey,TValue>  20、装箱和拆箱  21、读写数据(Ststem.IO)  22、文件流(FileStream)  23、StreamReader和StringWriter  24、File和Directory  25、序列化  26、Directory类的静态方法  27、正则表达式  28、Regex类  29、字符串提取  30、贪婪模式  31、字符串替换  32、byte数组和字符串的转换  33、委托  34、多播委托  35、事件  36、委托和事件的区别  37、var类型  38、扩展方法  39、XML

    1、构造方法(函数):在对象创建的时候初始化字段

        public 类名([参数])

        {

            //执行内容,如this.name=name;(有参数)

        }

      构造方法没有返回值,void也不写

      创建对象时如果没写构造方法系统默认有一个无参的构造方法,一旦用户添加了构造方法,原来默认的无参的构造方法就没有了

      默认初始值为:int:0;  bool:false;  string:null;   char:‘’; 

      构造方法的作用:初始化字段(实例化类的时候传入初始值)

      调用构造方法:

        1)除了new对象的时候,不能直接使用构造方法名调用构造方法

        2)this调用构造方法(难点)(一个构造方法调用另一个构造方法)

       为了解决代码的重用才使用this调用构造方法

       当一个类中出现多个构造方法重载的时候,同时构造方法都需要为字段赋初值

       使用this代表当前类的构造方法来使用,根据this后面的参数决定使用哪一个重载

        public 构造方法名():this([参数])

        {

            //代码

        }

    如:  

     public Person(string name, int age, string sex)

            {

                this.name = name;

                this.age = age;

                this.sex = sex;

            }

            public Person(string name)

                : this(name, 0, null)

            {

            }

    2、继承:

      多个类都有共同的字段、属性或方法时,可以使用继承

      需要写一个学生类、一个老师类、一个校长类

      事先写一个Person类,在写其他类的时候继承这个类,Person叫父类,继承他的叫子类

      特征:子类既有父类的非私有字段、属性和方法,又有子类独有的字段、属性和方法

      一个子类只能有一个父类,一个父类可以有若干个子类

        [访问修饰符] class 子类名:父类名

    子类调用父类构造方法的问题(难点)

      ->构造方法的执行顺序:先父类再子类

      ->关于构造方法的重载:如果不声明调用哪个构造方法默认执行无参的构造方法

      避免错误的方法:

    ->为父类提供无参构造方法

    ->在子类中指定调用父类有参的构造方法

    注意:父类除构造函数(方法)之外的非私有成员都可以被子类所继承,构造方法不可以被继承,但可以被调用,调用方法: [访问修饰符] 构造方法名([参数]):base(父类构造方法的参数)

    public Teacher():base("狗蛋”,20,"女")

            {        }    //直接赋值,实例化对象时不需再赋值

     

     public Teacher(string name, int age, string sex)

                : base(name, age, sex)

            {

                this.className = "C#";//老师类独有的字段

            }   //继承传递参数,实例化对象时需要赋值

      base关键字用于显示声明要调用父类的哪个构造方法,是调用,不是声明不是继承

      注意:为避免继承父类时因为构造方法出错,应该为每个声明的类都手动添加一个无参的构造方法

    3、访问修饰符

      public 最公开的,所有地方都可以访问

      private 最隐蔽的,只有本类可以访问

      protected 可以在当前类和子类中被访问

      internal 只能在本项目中被访问

      C#中规定类的访问修饰符只能是public 和internal 

      类中成员的访问修饰符除以上四种以外还有个(protected internal)即可以在当前类、子类和本项目中被访问  

    4、静态和非静态

      静态使用static标记

    静态成员

      ->如何定义静态成员

           在成员前加static关键字

      ->如何使用静态成员 

    静态成员不能由实例对象调用,只能用类名调用

    使用静态成员,不需要实例化对象

    静态成员会在整个应用程序退出时才释放资源,所以这个变量可以在整个程序中共享数据,可用于窗体间传递参数

    注意:静态变量过多会占用系统内存,因此声明静态变量时要多加考虑

    Main方法是静态的,所以它只能调用静态的方法或参数,若想调用非静态方法,必须new一个类的实例,用实例名调用。

    静态类

      1)什么情况下要将一个类标记为静态类?

          一般情况是,当这个类是一个工具类,里面都是方法,为了让用户调用的时候方便,不需要实例化对象,这时可以将该类标记为static类,此时该类中只能包含静态成员,不能包含实例成员,比如Convert、Console、Read、ReadInt等

      2)什么情况下需要在一个普通类中编写一个静态成员,而这个类不能标记为static?

          当这个类需要被实例化的时候,如果这个类中有一个成员是所有对象要共享的数据,这时可以将该类中的这个成员标记为静态的,但是这个类还是一个非静态类

      3)静态类不能被实例化,不能被继承

      4)由于静态成员会在整个程序退出时才释放资源,所以尽量避免写静态字段或静态属性,最好只写静态方法

      5)静态类中可以有静态成员和实例成员,因为其不能被实例化,所以静态类中的实例成员无法被调用,也就没有任何意义了

      6)静态类不能被继承,也不能继承自其它类,只能继承自Object类

    静态构造函数

      1)静态构造方法(或字段)在第一次访问这个类的时候执行,并且只执行一次

      ->静态构造方法与静态类的生命周期(了解)

    静态成员属于该类的所有对象。实例成员只属于当前实例

    静态类的生命周期:第一次访问类的时候创建,程序结束时才释放

     

    5、隐藏基(父)类方法(了解,用的不多)

      当子类和父类有相同名字的方法时,实例化子类调用该方法为子类内的方法,把子类转换成父类后再调用该方法就是父类内的方法了

      为了代码规范化,如要有意隐藏父类的方法,要在子类的同名方法前加new关键字,用于   提醒这里是要隐藏父类方法

    //隐藏基类方法

        class MyBase

        {

            public void Func()

            {Console.WriteLine("我是父类的方法);}

        }

        class MySub : MyBase

        {

            public new void Func() //在方法前用new关键字提醒这里是有意隐藏父类方法

            {Console.WriteLine("我是子类的方法);}

        }

        class Program

        {

            static void Main(string[] args)

            {

                MySub ms = new MySub();

                ms.Func();

               // ((MyBase)ms).Func();

                MyBase my = ms;

                my.Func();

                Console.ReadKey();

            }

        }

    6、重写基(父)类方法(多态的体现)

      在父类方法前加virtual(虚方法),表示这个方法可以被重写

      在子类方法前加override,表示重写基类方法,子类如果不写override就是隐藏

     当子类和父类有相同名字的方法时,实例化父类调用的是父类的方法,将子类赋值给父类后,父类调用的就是子类的方法了

      一旦父类的方法在子类中被重写,除了实例化父类调用以外,子类或者子类的子类调用时都是调用的最新的那个子类重写方法

      此时base和this就有区别了:

      如果子类和父类中有名字相同的方法,那么base.Func()就代表父类的方法,this.Func()代表当前类的方法

      如果不希望子类再重写,需要在子类方法前加sealed

    //重写基类方法

        class USB

        {

            public virtual void Usb() //virtual关键字表示父类方法可以被重写′

     

            {Console.WriteLine("我是父类的方法);}

        }

        class Phone:USB

        {

            public override void Usb()//override关键字表示这个方法重写父类的方法

     

            {Console.WriteLine("手机");}

        }

        class Mp3:USB

        {

            public override void Usb()

            {Console.WriteLine("MP3");}

        }

        class Program:USB

        {

            static void Main(string[] args)

            {

                Console.WriteLine("输入数字");

                USB usb = new USB();

                switch (Console.ReadLine() )

                {

                    case "1":

                        usb = new Phone();

                        break;

                    case "2":

                        usb = new Mp3();

                        break;

                    default:

                        break;

                }

                usb.Usb();

                Console.ReadKey();

            }

    }

    隐藏看类型,重写只管新

    7、抽象方法

      方法前加abstract,圆括号后加分号

      [public]  abstract  void 方法名(参数);

      抽象方法所在的类也必须是抽象的,不能被实例化,类前加abstract  

      abstract  class  类名

      抽象成员必须出现在抽象类中,但抽象类中可以有抽象成员和实例成员

      抽象类的抽象方法默认可以且必须被重写,所以需要重写时不需要再写virtual,直接在子类方法中写override关键字即可重用

      抽象类的成员:方法、属性、索引、事件

      注意:抽象类中的所有抽象方法在子类中必须要被重写,如果子类中不重写,那这个子类也必须声明成抽象类,但此时子类也就不能被实例化了

    8、接口

      [访问修饰符] interface 接口名(接口一般以I开头,I+行为+able)

      {

        //接口成员,一定是抽象成员

      }

      成员的定义:与抽象成员的写法一样(没有关键字),没有执行体(方法体);没有访问修符;

      实现:子类“继承”自接口,接口可以看做是子类的“干爹”,补全抽象的方法

      调用:和类的使用方法一样,要使用接口中的方法,则将对象赋值给接口变量

      多态:和抽象类的实现一样,接口的多继承使得多态的实现变得灵活

      子类继承父类,子类实现(继承)接口:class 子类名:父类名,接口名 或class 类名:接口名

      个人理解:接口就是把类中的一种特定的功能性方法封装成接口(如开车、飞等),声明类的时候可以继承这个接口,就拥有了这个接口所特有的功能,就可以在类中实现这个功能,那实现后的这个功能就成为了这个类的一个功能性方法。用接口可以实现多继承,一个类可以继承多个接口,也就拥有了多个功能性方法,声明类的时候可以选择性的继承,比如定义老师的时候可以继承说话、吃饭、教课等接口,定义司机的时候又可以继承说话、吃饭、开车等接口

    //定义一个接口,表示Driving功能

    interface IDrivable

        {

            void Driving();

        }

    class Teacher:Person,IDrivable//继承父类和接口

        {

            public Teacher(string name, int age, string sex):base(name,age,sex)

            {//继承父类的构造方法

            }

            public void Driving()//实现接口的Driving功能

            {

                Console.WriteLine("我会开车");

            }

            public override void ShowMe()//重写父类方法

            {

                Console.WriteLine("我是老师");

            }

        }

    static void Main(string[] args)

            {

                Teacher tea = new Teacher("张三", 18, "男");

                tea.ShowMe();//调用重写后的方法

                tea.Driving();//调用实现后的接口方法

                Console.ReadKey();

            }

    9、多态和接口

      接口是可以多继承的,多继承同时会引起方法的重名

      为避免重名,显示实现接口:

    返回值 接口名.方法名(参数)

       {

            //方法体

       }

    显示实现接口的这个方法只能由接口变量进行调用

    现阶段记住接口使用的语法,然后将接口直接当做抽象类使用(初学阶段)

    10、值类型和引用类型

      变量可以看做是一个数据

      值类型,是一个存储数据的容器,这个数据就是这个类型表示的数据

      引用类型,也是一个容器,但是这个容器存储对象的一个引用(地址),真正的数据在另一块内存中,就相当于是一个指向数据的快捷方式

      值类型存储在栈里面,引用类型存储在栈和堆里面(堆里存储的是真实数据,栈里面存储的是真实数据在堆里面的内存地址)

      值类型和引用类型会涉及到传参和赋值时的不同,要注意区分

     

      委托(delegate)也是引用类型

      值类型赋值赋的是真实的值,引用类型赋值赋的是地址

      引用类型是一个变量,两个快捷方式,修改一个快捷方式会影响另一个快捷方式;值类型是一个变量和一个复制后的变量,修改一个变量不会影响另一个变量

      所有的值类型都继承自System.ValueType类

    11、引用传递:ref和out

      使用ref或out就可以实现将引用传递过来

      定义方法时,在参数类型前加ref或out

      调用方法时,在参数前加ref或out

      注:定义变量时不需要加ref或out

      当一个变量传递给一个方法时,总是复制一份自己的数据,赋值给方法,那么方法中执行的变量就与方法外的那么变量没有关系了,方法内修改变量值,也不会影响方法外的那个变量。有时会要求多个返回操作(方法中的变量有多个在方法外需要使用),此时可以使用ref标记参数,此时在方法中使用的这个变量与方法外的变量就是同一个变量了,相当于可以使用参数实现返回值

        out与ref的作用与使用方法相同

      out 必须在方法中赋值

      ref必须在方法外赋值

    12、类型转换

      隐式类型转换:兼容类型,小转大

      显式类型转换:即强制类型转换  (转换后的类型)要转换的变量

      Convert类型转换:系统封装的方法,Convert.ToInt32()、Convert.ToDouble()等

      其他转换方法:int.Parse()、int.TryParse()(第一个参数表示待转换的字符串,第二个out(result)参数表示数字转换成功后的变量,如果转换失败,返回false,为out result赋值为0)

      用int.TryParse()代替try-catch,释放内存,提高性能

      不止int类型有TryParse,所有基本类型都有TryParse,用法都一样

    13、异常处理(try-catch、try-catch-finally、try-finally)

      Exception是一个专门用来封装异常的一个类型

      两个属性:message(异常说明文本)和stackTrace(异常抛出的顺序)

      抛出异常:throw Exception的一个对象(new一个对象)

      从出现异常的try向上依次抛出(方法之间依次调用),直至处理,找到最近的catch捕获异常(用于try-finally语句,catch块在方法以外,执行顺序是try-finally再向上寻找catch执行异常捕获)

    Finally用于释放资源,finally{},程序执行完try-catch后会再执行finally语句块

    Finally总会执行,即使try-catch中有return

               try

                {  }

                catch (Exception ex)

                { throw; }

                finally

                {  }

    Try-finally用处不多,用于释放资源

    使用异常会降低系统性能,尽量少用

    14、string字符串处理

    构造函数:string(char[] chs)、string(char ch,int count)

      string str = new string(’a‘,’b’,’c’);//abc

      string str = new string(‘a’,3);//aaa

      3.144.ToString(“0.0”);用于控制格式,会四舍五入

    字符串可以当做数组进行处理(使用下标读取,拥有数组的各种属性)

      string str = “不可见的你”;  此时str[1]就是“可”了

      通过索引得到的数据是char类型,字符串不可改变,使用索引无法修改字符串的数据

      要想修改可将字符串变成字符型数组,str.ToCharArray()

    string是引用类型

    string str = string.Empty;声明一个空字符串

      判断字符串是否为空:

    str.Length == 0(推荐)

    str ==“”

    str == string.Empty

    String.IsNullOrEmpty(要判断的字符串)(推荐)

    15、string常用方法

      1)字符串比较:bool isTrue = string.Equals(string a,string b)

      String.Equals(str1,str2);

      Str1.Equals(str2,StringComparison.OrdinalIgnoreCase); //第二个参数意思是不区分大小写

      string.Compare(str1,str2);

      Equals方法:

    String重载的方法判断两个,一个是==,一个是EqualsHelper

    ==判断两字符串是否相同

    EqualsHelper判断两个字符串中每一个字符是否相同

      Object的重载是来自于object类,是继承下来的

    在object中使用的是==和Equals方法

    Equals方法是一个虚方法,由string重写了,调用的是object.ReferenceEquals方法和EqualsHelper方法

    注意:==默认表示判断两个对象的地址是否相同,与object.ReferenceEquals方法一样

    String提供的str1.Equals(str2)判断地址是否相同,字符串是否object提供的virtual Eaulse(object)

    Equals和==的区别:

      Equals会判断两个值的内存地址;==只判断值是否相等。

    Compare方法:

      int result = String.Compare(str1,str2);

      str1>str2 -> 1    str1 == str2 -> 0   str1<str2 -> -1

      string.Compare方法比较两个字符串,这两个字符串字母顺序表示大小,按照字典排序规则进行比较(对于char类型:A>a,B>a,b>A同一个字母,大写>小写,不同字母按照字母顺序后面的大于前面的;对于string类型不是按照埃克森码比较,A>a,b>A,B>a)

      2)大小写转换:ToLower()和ToUpper()

      3)str1 = str1.Trim([params char[] chs]);去除字符串两边的空格,或chs中出现的字符(重载)

         str1 = str1.TrimEnd(params char[] chs);去除字符串的末尾chs中出现的字符

         str1 = str1.TrimStart(params char[] chs);去除字符串的开头chs中出现的字符

      4)合并与分割

    合并字符串:string s = string.Join(str1,str2,str3,...)

    分割字符串:string[] strArray = str1.Split(‘a’);

                    string[] strArray= str1.Split(new char[]{‘a’,’b’},StringSplitOptions.RemoveEmptyEntries);去掉a、b和所有空格

      5)字符串查找

    Contain包含,返回bool类型的值,str1.Contain(“爱”);

    IndexOf检索位置,返回字符串中某个字符的位置(int)找不到则返回-1

    str.IndexOf(要找的字符或字符串)

    str.IndexOf(要找的字符或字符串,开始寻找的位置)

    str.LastIndexOf()是从后往前寻找,用法同str.IndexOf() 

    注意:IndexOf和LastIndexOf中第二个参数(开始寻找的位置)只是为了说明要查找的是字符串中的哪一个字符(如果字符有重复),即按查找顺序在开始位置后的第一个字符,返回的索引依然是该字符在整个字符串中的索引,而不是从查找位置开始的索引。

      6)截取子字符串

    string s =str1.Substring(开始的位置,子字符串的长度)

    String s = str1.Substring(开始的位置)

      7)判断字符串的开头和结尾

    bool a = str1.StratWith(字符串);

    bool a = str1.EndWith(字符串);

      8)字符串的插入、移除和替换

    插入:string str2 = str1.Insert(位置(int),要插入的人字符串(string));

    移除:string str2 = str1.Remove(位置(int),长度(int));

          string str2 = str1.Remove(位置(int));移除该位置后的所有字符

    替换:string str2 = str1.Replace(旧字符串,新字符串);

      9)格式化字符串

    String.Format(格式化的字符串,填坑的参数)

    string str1 = String.Format(“{0},{1}”,str2,str3);

      10)判断字符串是否为空

        String.IsNullOrEmpty(str);

      10)字符串的方法(总结)

    增:添加(+=)、插入(Insert)

    删:Remove

    改:Replace、 ToUpper、ToLower、Trim、TrimStart、TrimEnd、Split、Join、new String、SubString、Format

    查:Contains、IndexOf、LastIndexOf、StartsWith、EndsWith、ToCharArray、Length、Empty

    比:Equals、Compare

    16、StringBuilder

    大量字符串拼接的时候性能非常差,很难完成大型数据的拼接

    (Stopwatch对象可以记录程序运行的时间,Start开始计时,Stop结束)

    使用StringBuilder:StringBuilder sb = new StringBuilder();

      sb.Append(要添加的字符串);//向sb中添加数据

      sb.AppendLine(要添加的字符串);//向sb中添加数据后换行,等价于sb.Append(要添加的字符串+” ”);

      sb.AppendFormat(要添加的字符串);格式化处理,等价于 sb.Append(string.Format(要添加的字符串));

      string str = sb.ToString;输出或赋值时要转换成string

    在处理大型数据的时候,StringBuilder要比普通的string处理快很多,因为处理大型数据要用StringBuilder

    17、读取文件

      string[] lines = File.ReadAllLines(@"H:传智播客实训资料代码第9天a.csv", Encoding.Default);//按行读取

      string[] lines = File.ReadAllText(@"H:传智播客实训资料代码第9天a.csv", Encoding.Default);//读取所有文本

      string[] lines = File.ReadLines(@"H:传智播客实训资料代码第9天a.csv", Encoding.Default);//读取一行文本

      string[] lines = File.ReadAllBytes(@"H:传智播客实训资料代码第9天a.csv", Encoding.Default);//读取字节

    18、文本高亮

    ->让文本框获得焦点--txtContent.Focus();

    ->找到要高亮的位置--pos

    ->选中(高亮)的字符串长度--length

    ->调用TextBox的选中方法txtContent.Select(pos,length)

    19、泛型集合   List<T>和Dictionary<TKey,TValue>

    List集合:动态的自定义数组

      List<类型> 集合名 = new List<类型>();

    List用法与ArrayList一样,不同点在于定义时和使用时的类型固定,因此可以完全替代ArrayList

      类型[] = list.ToArray()//将List转换成该类型的数组

    Dictionary集合:动态的自定义键值对

      Dictionary<类型,类型> 集合名 = new Dictionary<类型,类型>();

    Dictionary用法与Hashtable一样,不同点在于定义时和使用时的类型固定,因此可以完全替代Hashtable

    20、装箱与拆箱

      直接将值类型赋值给引用类型就是装箱

      将存储值类型的引用类型强制转化为对应的值类型就称为拆箱

    Object o = 1;//装箱      int n = (int)o;//拆箱

      装箱对值类型保持无关性,装箱对引用类型保持相关性

      装箱和拆箱会对性能有一定的影响

    21、读写数据(I/O操作、System.IO类)

      System.IO.Path类,专门处理字符串路径,是一个静态类

        string path = @“D:windowsystemfile.txt”; 

        获取文件名:string fileName = Path.GetFileName(path);

        获取后缀名:string fileName = Path.GetExtension(path);

        修改后缀名:path = Path.ChangeExtension(待修改的路径,“mp3”);

        获取文件夹名:string fileName = Path.GetDirectoryName(path);

        合并路径:path= Path.Combine(路径1,路径2,路径3...);

        临时文件夹:path = Path.GetTempPath();

      绝对路径:从盘符开始的最精确的路径

      相对路径:相对于当前文件同一个目录作为参照的路径

      相对路径和绝对路径:区分就看有没有根目录盘符的标记

    22、文件流(FileStream)

      1)引入命名空间

      2)创建FileStream对象FIleStream fs = new FileStream(文件名,FileModel,FileAccess)

    FileStream fs = new FileStream(@"D:a.txt", FileMode.Create, FileAccess.Write);

    FileModel:对文件的处理方式(打开、创建、追加)

    FileAccess:对文件的操作:读、写

      3)使用方法操作

    写一个字节:fs.WriteByte()

    写一个字节片段(将字节数组中的数据写入到fs指定的文件):

      fs.Write(存放字节的数组,开始写字节的数组下标,要写的字节数)

    读一个字节:fs.ReadByte()

    读一个字节片段(将fs指定的文件中的数据读取到字节数组):

      fs.Read(存放字节的数组,开始存放字节的数组下标,要读的字节数)

      4)释放资源

    fs.Close()和fs.Dispose()方法(两个都要调)

    23、StreamReader和StreamWriter

      StreamReader:专门用来读取文本文件的流

    1)引入命名空间:IO

    2)new一个FileStream指向文件

    3)new一个StreamReader,构造函数参数是FileStream的对象

    4)调用方法

        StreamReader有一个属性EndOfStream:判断当前的流位置是否在文件流的末端,一般用来判断文件是否读完

      StreamWriter:专门用来写入文本文件的流

    1)引入命名空间:IO

    2)new一个FileStream指向文件

    3)new一个StreamWriter,构造函数参数是FileStream的对象

    4)调用方法

    24、File和Directory对文件和目录操作做了一个封装

    增(Create):创建文件或文件夹  

    删(Delete):删除文件或文件夹  

    改:改名字 File.Move(“1.txt”,“2.txt”)

    查:...

    判断是否存在(Exists)

    移动文件:File.Move(“1.txt”,“21.txt”)

    复制文件:Copy

      Directory用于处理文件夹(目录)

    删除目录的时候如果目录不是空的则会报错,此时需要在Delete内添加一个true

    Directory.Delete(“1”,true);

    25、序列化:

      序列化:把一个对象的内容存储到磁盘上(文件流)、网络上(网络流)、内存里(内存流),下次需要用到对象数据的时候可以直接拿来用

      反序列化:把已经序列化存储到磁盘、网络、内存里的对象数据,提取到项目中的对象中

    序列化步骤:

    1)创建一个文件流

    2)为需要序列化的对象添加标记([Serializable]表示此对象可以被序列化)

    3)创建BinaryFormatter(导入命名空间)

    4)调用Seralize方法(bf.Seralize(文件流对象,需要被序列化的对象))

    反序列化步骤:

    1)创建一个文件流

    2)为需要序列化的对象添加标记([Serializable]表示此对象可以被序列化)

    3)创建BinaryFormatter(导入命名空间)

    4)调用DeSeralize方法(object ob = bf.DeSeralize(文件流对象))

    反序列化定义接收类型的时候必须根据原序列化的程序集确定类型

      建议:在使用序列化的时候尽量避免使用自动属性,因为自动属性在每次编译的时候自动生成的字段名可能不一样,所以在反序列化的时候可能会造成问题

      注意:如果序列化和反序列化不在同一项目下,那反序列化的时候需要引用原序列化的程序集

    26、关于文件夹下的文件与子文件夹

      Directory类的静态方法

    获取子文件名:string[] s = Directory.GetFiles(@“D:dir“);

    获取特定后缀名的子文件名:string[] s = Directory.GetFiles(@“D:dir“,”*.txt“);

    获取所有文件夹名:string[] s = Directory.GetDirectories(@“D:dir“);

    27、正则表达式

      元字符:

    1).(点)表示除 以外任意的单个字符

    2)[ ]表示括号内的任意一个字符(如a[xyz]b表示axb或ayb或azb)

    3)^在[ ]括号内表示取反(如^[a-z]表示除小写字母以外的所有字符)

    4)^匹配一串字符的开始(^abc表示以abc为开头的任意字符串)

    5)$匹配一串字符的结尾(abc$表示以abc为结尾的任意字符串)

    5)|表示“或”,优先级最低(如a|bc表示a或bc,(a|b)c表示ac或bc)

    6)()可以改变优先级、提取组

    7)*表示限定前面的字符出现任意次数(abc*表示ab、abc、abcccc......(abc)*表示abc、abcabc)

    8)+ 至少出现一次,也可出现多次(xa+y表示xay、xaay...)

    9)?表示出现0次或1次

    10){n}限定前面的表达式出现n次

    11){n,m}至少出现n次,最多出现m次

    12){n,}至少出现n次

    13)d表示0-9,D表示d的反面

    14)s表示空白符,S表示s的反面

    15)w表示数字、字母、下划线、汉字,W表示w的反面

    注:正则表达式的转义符也是,如果要表示*(星),可以写成*,要表示一个,可以写成\

    28、Regex类

      Regex.IsMatch(待判断的字符串,正则表达式)判断一个字符串是否匹配某个正则表达式

      !如果正则表达式没有^和$,那默认不设定开头和结束,此时只要待判断的字符串中含有该正则表达式就返回true

      ^z|food$:表示以z开头的任意字符串或者以food结尾的任意字符串,都返回true

                 因为|的优先级最低,所以上边的表达式其实是(^z)|(food$)

      Regex.Match()从某个字符串中提取匹配某个正则表达式的某个子字符串,但只能提取一个

      Regex.Matches()同上,可以提取所有的匹配字符串

      Regex.Replace()字符串替换,把所有匹配正则表达式的字符串替换为对应的字符

    29、字符串提取

      字符串提取的时候一般不加^和$  

      Match m = Regex.Match(原字符串,要提取的正则表达式)

      m.Value属性表示提取到的字符串

      m.Group[n]:提取组,按正则表达式中()括号对的个数,m.Group[0]表示整个字符串,m.Group[1]表示第一个括号内的内容,所以提取组的时候要从下标1的地方开始

      MatchCollection mc = Regex.Matches(原字符串,要提取的正则表达式)

      MatchCollection是一个集合,需要foreach遍历输出(遍历时的类型是Match)

    30、贪婪模式

      定义:当正则表达式提取的时候,如果一个字符或多个字符都能匹配,这时会按照使用最多字符的方式来匹配。

      正则表达式默认采用贪婪模式,尽多的匹配

      在限定符后面使用问号用来终止贪婪模式,即只会提取匹配的第一个

      string s = “aaaa bbbbbbbb”;string s1 = “[a-zA-Z]+”;  匹配结果:aaaa

      string s = “aaaa bbbbbbbb”;string s1 = “[a-zA-Z]+?”;  匹配结果:a

    31、字符串替换

      String s =Regex.Replace(原字符串,待替换的正则表达式,替换后的字符串);

      如:string s = Regex.Replace(s, "-+", "-");//把字符串s中的所有-替换成一个-

      提取组替换:

                string s = "aaa13812345678bbb";

                s = Regex.Replace(s, @"(d{3})(d{4})(d{4})", "$1****$3");//把手机号中间4位替换成4个*

    32、byte数组和字符串的转换

      byte[] bt= System.Text.Encoding.UTF8.GetBytes(str);

      string str = System.Text.Encoding.UTF8.GetString(bt);

    33、委托(delegate)

      委托是一种数据类型(和类一样),可以将方法赋值给委托对象,可以理解为方法类型

      定义(在命名空间下,或添加一个cs文件,和类的定义一样):

    1)使用delegate关键字

    2)这个委托将来要存储的方法如果没有返回值,那么委托也要定义成void,参数也要与方法保持一致

    3)委托是一个数据类型,用的时候需要传递一个变量

    4)创建委托对象的时候可以不用new,系统编译时会自动给我们new

    定义委托类型:public delegate void ChangeTxtDelegate(string str);

    创建委托对象:public ChangeTxtDelegate changeTxt;  //Form1中

        给委托赋值:f1.changeTxt = ChangeText;  //Form2中

    调用委托:changeTxt(txt);  //Form1中,此种调用方法为简写,实际上是changeTxt.invoke(txt);

    创建委托对象时也可直接对其赋值:ChangeTxtDelegate changeTxt = new ChangeTxtDelegate(ChangeText) ;

      用法(窗口间传值):委托要声明在需要被传值的对象内,比如Form1要提取Form2中的数据(即Form2往Form1传值),就应该把委托声明在Form1中,在Form2中写一个方法获取要传的数据,并且赋值给Form1的委托,最后在Form1中调用委托就ok了。(委托声明位置不绝对,还需要考虑当前活动窗口的问题,要声明再活动窗口中,有时也可声明在被提取值的窗口内)

      作用:可以在某个代码内部,嵌入一段外部代码(外部写一个方法赋值给委托或在定义方法时把委托类型作为参数,调用时把方法名作为参数传递给委托对象,那么委托就执行该方法,不同的外部项目可以写不同的方法赋值给委托,可以实现一个委托选择性执行多种方法的灵活性),相当于是注入

      什么情况下使用委托?

        当一个类型中需要嵌入一段代码,但是这段代码具有不确定性,是根据使用这个类型的用户来确定代码的,这时就可以在该类型中使用一个委托,保证在某种情况下会调用该委托,用户将对应的方法传递给该委托,就会调用这个方法

      可以把静态方法或者私有方法赋值给委托了变量,赋值后只要能使用到该委托变量的地方就能使用该方法,打破了访问修饰符的限制

      一般在调用委托前或者触发事件前,都要判断委托变量或事件是否为null,如果为null则不调用

    34、多播委托

      MyDelegate md = new MyDelegate(M1);  md+=M2;(增加某个方法)md-=M4;(去掉某个方法)

      使用委托时,如果不是+=而是直接用=赋值,则会将前面增加的所有方法都覆盖掉

      多播委托可以存储多个方法,委托中方法调用的顺序与增加方法时的顺序是一致的,但是,不要依赖于这个顺序(微软没有承诺这样的顺序,万一以后改了就GG了)

      多播委托中,如果要是有返回值,只会得到最后一个方法返回的结果。可以通过调用GetInvocationList()方法返回当前委托中的所有方法,返回值类型时一个Delegate数组(委托数组),再用foreach遍历调用所有方法

      所有定义的委托都继承自抽象类MulticastDelegate,而MulticastDelegate又继承自Delegate抽象类

      多播委托内部是将绑定在当前委托对象上的每个方法,都转换成一个委托对象,并且存储在了一个叫_invocationList的object数组中。当调用委托的时候,其实就是循环遍历_invocationList数组,并且调用其中的每个委托

      多播委托中,如果其中的某个方法执行时发生了异常,则后面的方法不再执行。

      多播委托中只能存储同一类型的委托,即返回值、参数都相同

    35、事件

      事件是在特定条件下执行的动作,这个动作是由用户确定的。如Button的Click事件,其动作是由程序员写的,因此可以用委托来实现这个功能,写不同的方法赋值给委托变量。

      但用委托模拟方法有两个缺点:

      1)定义的委托可以在类外部的任何地方被触发,即非特定条件下也可以调用。因为委托变量是public修饰,改为private就不能在外部赋值了。

      2)由于委托可以用=(等号)赋值,所以就有可能把前面已经注册的事件处理程序都覆盖掉。

      而用事件就可以解决以上问题:

      1)用事件必须先定义一个委托,否则无法使用事件

      2)实例化委托变量的时候,在委托类型名前面、访问修饰付的后面加event关键字,就定义了一个事件

      3)使用方法与委托一样,只是避免了以上两个问题

      4)由于事件只能有+=或-=赋值,所以就避免了用=(等号)赋值时覆盖前面事件处理程序的问题

      5)由于事件不能在定义事件的类以外被触发,所以也就避免了冒充事件触发的问题。

    36、委托和事件的区别(面试常考)

      委托和事件没有可比性,委托是数据类型,事件是委托类型的变量

      委托可以用+=、-=、=赋值,可以在类的外部被调用

      事件只能用+=、-=赋值,不能在类的外部被调用

      事件的内部是用委托实现的

      事件的作用和委托变量(不是委托,是委托变量)一样,只是在功能上受到一定的限制

    37、var类型

      var只能用作局部变量,可以赋任何类型的值。

      var a = 1;和int a = 1;两者完全一样

      var不能作为类的成员的类型,不能用作参数,不能用作返回值,只能用作局部变量

    38、扩展方法(不修改微软系统方法源代码,实现系统方法的增加)

      1)添加一个静态类

      2)在静态类中增加一个静态方法,方法参数是:(this+要扩展的类名+变量名,该方法的参数)

      如要在string类中添加一个验证是否是Email格式的扩展方法:

            public static bool IsEmail(this string str)

            {

                return Regex.IsMatch(str, @"^w+@w+.w+$");

            }

                string a = "1321321@qq.com";

                Console.WriteLine(a.IsEmail());

      扩展方法只是看起来像类中的方法,其实不是,所以在扩展方法中也访问不到类中原来的私有成员

      因为会扰乱系统方法,所以不建议使用,尽量不用

    39、XML

      XML是用一种格式化的方式来存储数据,可以用记事本打开

      1)XML有且只有一个根元素

      2)有开始标签就必须得有结束标签,且区分大小写

      3)元素的属性值要用引号

      读取XML文件,通过XDocument(需要添加命名空间)

      读取整个XML文件: XDocument xd = XDocument.Load(XML文件路径)

      循环遍历每个节点:

    1)获取根节点  XElement xeRoot = xd.Root;(xeRoot.ToString()表示XML文档的内容)

    2)递归遍历XML中的每个节点

      遍历xeRoot下面的所有子节点:

         public static void GetEle(XElement xe)

                {

                    foreach (XElement ele in xe.Elements())

                    {

                        Console.WriteLine(ele.Name);

                        GetEle(ele);

                    }

                }

               GetEle(xeRoot);

    例:读取XML数据

    <CFX>

      <MSG>

         <交易码val="1000" />

         <流水号val="100000000000000001" />

         <金额val="1234567890.12" />

         <付款机构val="1234" />

         <付款单位账号val="12345678901234567890" />

         <收款机构val="1234" />

         <收款单位账号val="12345678901234567890" />

      </MSG>

      <MSG>

         <交易码val="1000" />

         <流水号val="100000000000000002" />

         <金额val="1234567890.12" />

         <付款机构val="1234" />

         <付款单位账号val="12345678901234567890" />

         <收款机构val="1234" />

         <收款单位账号val="12345678901234567890" />

      </MSG>

    </CFX>

        VS中读取XML的数据:

                XDocument xd = XDocument.Load("ytbank.xml");  //加载XML文件

                XElement xeRoot = xd.Root;  //获取根节点

                foreach (XElement item in xeRoot.Elements())  //遍历根节点,获取第一级子节点(MSG)

                    {

                      foreach (XElement itema in item.Elements())  //遍历第一级子节点,获取第二级子节点

                        {

                        Console.WriteLine("{0}:{1}", item.Element(itema.Name).Name, item.Element(itema.Name).Attribute("val").Value);  //获取节点名和属性值

                        }

                    Console.WriteLine("==================================");

                  }

    XML写入:

                XDocument xdoc = new XDocument();  //创建一个XML对象

                XElement xeleRoot = new XElement("Websites");  //创建一个根节点

                xdoc.Add(xeleRoot);  //将根节点添加到XML文件中

                xeleRoot.SetElementValue("baidu", "http://www.baidu.com");  //添加一个节点以及内容       

                XElement xeleGoogle = new XElement("website");  //创建一个节点

                xeleGoogle.SetAttributeValue("url", "http://www.google.com");  //添加属性和属性值

                xeleGoogle.SetElementValue("name", "谷歌"); //为节点添加子节点

                xeleGoogle.SetElementValue("age", "14");

                xeleGoogle.SetElementValue("boss", "谢盖尔");

                xeleRoot.Add(xeleGoogle); //将节点添加进根节点

                xdoc.Save("website.xml");  //保存一个XML文档路径

     

     

               

     

     

    作者:七步、 出处:http://www.cnblogs.com/dongyu9521/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    c# DES加密解密
    命令行远程调用图形界面程序
    mpv0.29 vo=x11 resize窗口渲染存在不正常黑色显示
    记qt 焦点状态在多个子窗口的关系
    linux_虚拟机终端连接方法
    python_爬虫_微信公众号抓取
    python_爬虫_multiprocessing.dummy以及multiprocessing
    python_爬虫_腾讯新闻app 单页新闻数据分析爬取
    python_爬虫_Charles手机证书安装问题
    python_爬虫_Selenium_Error
  • 原文地址:https://www.cnblogs.com/dongyu9521/p/3871507.html
Copyright © 2011-2022 走看看