码迷,mamicode.com
首页 > Web开发 > 详细

如鹏网学习笔记(三).Net高级技术

时间:2017-08-19 16:59:31      阅读:206      评论:0      收藏:0      [点我收藏+]

标签:param   har   笔记   over   序列化   exception   get   元数据   组合   

 

net高级技术

一、多项目开发
1,添加对项目的引用
  //新建一个类库,用来放公共的要使用的类,使用的时候别的项目去引用它
  //using 类库文件;

  注意事项:注意被引用的类要使用public修饰
  被引用的程序集中的类的修饰符,如果不写的话,默认是internal。
  效果是,只有当前程序集(类库)内部才能访问。

2,多项目时候的配置文件的读取问题
  a,只有主项目的配置文件才起作用(当前启动的)
  b,config文件不能改名,不能建多个config,在config里面也不能建多个AppSettings段

3,在项目中“转到定义”,是看不到源代码的,可以使用反编译工具查看

4,调用第三方dll(类库文件)的方法
  a,自己的项目就使用项目之间的引用方法
  b,使用别人写好的dll就用:添加引用-浏览-选择要添加的dll文件


二、索引器 indexer
1,索引器:没有名字,索引器的内部本质

2,可以是只读或者只写

3,为什么字符串只能char ch = s[5];不能s[5] = ‘a‘
  字符串的不可变性;
  只读索引

  public char this[int index]{get;}


三、密闭类和静态类

1,密闭类 sealed

   不能有子类。适用于系统中的基本类,比如String类。可以new对象

2,静态类 声明为 static

   没法创建对象,没法New; 无法创建子类,只能声明static成员(方法或者变量)
  适用于工具类,不需要new,直接调用它的静态方法或者属性

3,扩展方法
  使用方法:
  声明一个静态类,增加一个静态方法,第一个参数是被扩展类型,标记为this,
  然后在其它类中可以直接调用,也可以使用普通静态方法的方式调用,所以不能访问private和protected成员。

四、深拷贝、浅拷贝
1,引用类型对象变量赋值的时候指向同一个对象

2,可以通过自定义一个拷贝方法赋值出来一个新的对象

3,如果对象之间有引用关系,如果拷贝的时候共享被引用的对象就是浅拷贝,如果被引用的对象也拷贝一份出来就是深拷贝

  拷贝一个对象的引用,叫浅拷贝。
  如果被引用的对象也拷被拷贝了,叫深拷贝

五、结构体 struct

  是值类型,拷贝副本,不能继承,一个结构不能从另一个结构或者类继承。但是,结构从基类Object继承

  struct Person
  {
    public int Age{get;set;}
    public String Name{get;set;}
  }

六、值类型和引用类型
  两者之间的区别:
  引用类型变量的赋值只复制对象的引用;引用类型在堆内存(malloc);

  值类型变量赋值会拷贝一个副本;值类型在栈内存;

  值类型一定是sealed;


七、CTS,CLS,CLR,垃圾回收GC

  通用类型系统CTS,Common Type System

  通用语言规范CLS,Common Language Specification

  公共语言运行时CLR,Common Language Runtime

  垃圾回收 GC, Garbage Collection

  1,.Net平台下不只有C#语言,还有VB.Net、F#等语言。IL是程序最终编译的可以执行的二进制代码(托管代码)
    不同的语言最终都编译成标准的IL(中间语言,MSIL);这样C#就可以调用VB.Net写的程序集(Assembly,dll、exe)
    在.Net平台下:不同语言之间可以互联互通、互相调用

  2,不同语言中的数据类型各不相同,比如整数类型在VB.Net中是Integer、C#中是int。
    .Net平台规定了通用数据类型(CTS,Common Type System),各个语言编译器把自己语言的类型翻译成CTS中的类型。
    int是C#中的类型,Int32是CTS中的类型;int是C#中的关键字,但Int32不是

  3,不同语言的语法不一样,比如定义一个类A继承自B的C#语法是class A:B{},VB.Net的语法是Class A Inherits B。
    .Net平台规定了通用语言规范(CLS, Common Language Specification )

  4, IL代码由公共语言运行时(CLR, Common Language Runtime )驱动运行,
    CLR提供了垃圾回收
    (GC, Garbage Collection,没有任何引用的对象可以被自动回收,分析什么时候可以被回收)、JIT(即时编译器);

  5,值类型是放在“栈内存”中,引用类型放到“堆内存”,栈内存会在方法结束后自动释放,“堆内存”则需要GC来回收

八、装箱和拆箱

  值类型赋值给Object类型变量的时候,会发生装箱:包装成Object

  Object类型变量赋值给值类型的时候会发生拆箱,需要做显示转换。

  int i = 10;//值类型赋值
  object obj = i;//装箱,不需要进行显示转换,属于隐式转换
  int j = obj;//这里报错,发生拆箱,需要进行显示转换 //int j = (int)obj;

  注意:在拆箱的时候一定要显示转换回装箱时候的数据类型,否则会报错!!

九、比较相等的问题

  1,查看两个对象是否是同一个对象:对象1.RefrenceEquals(对象2);

  2,String对象的==方法只是比较内容!

  3,Object的Equals方法也比较两个变量指向的是否是同一个对象;对象如果override了Equals方法,就可以进行内容的相同比较

  4,默认情况下==不是调用Equals方法,需要重载==运算符

  5,String等这些类是重写了Equals方法

十、字符串缓冲池

  1,因为字符串的不可变性,字符串一旦被声明,就会一直存在,直到GC判断为未使用对象,被回收

  2,字符串是引用类型,程序中会存在大量的字符串对象,会浪费内存、导致性能低下,

  因此CLR提供了“字符串缓冲池”,如果发现同样内容的字符串对象,再声明时,直接拿来原来的对象
  (对字符串对象进行了重用)

    string s1 = "rupeng";
    string s2 = "rupeng";
    string s3 = "ru" + "peng";
    string s4 = new string(s1.ToCharArray());
    string s5 = new string(new char[]{‘r‘,‘u‘,‘p‘,‘e‘,‘n‘,‘g‘});
    Console.WriteLine(Object.ReferenceEquals(s1,s2));//true,字符串缓冲池的作用,两个字符串引用指向同一个对象
    Console.WriteLine(Object.ReferenceEquals(s1, s3));//true,编译器优化,先进行拼接,后进行赋值
    Console.WriteLine(Object.ReferenceEquals(s1, s4));//false
    Console.WriteLine(Object.ReferenceEquals(s1, s5));//false
    Console.WriteLine(Object.ReferenceEquals(s4, s5));//false

十一、ref和out

  ref 方法参数的修饰符
  1,方法内部修改外部变量的指向;

  2,变量传入前必须被赋值;

  3,在方法中不是必须被赋值;

  out 方法参数的修饰符

  1,方法需要多个返回值的时候使用

  2,变量传入前不用被赋值,赋值也没用

  3,在方法中必须对参数进行赋值

十二、委托

  1,委托是一种数据类型,指向一个方法;委托是引用类型,变量可以是null

  2,声明委托的方式:

    delegate 返回值类型 委托名(参数1,参数2,。。。);比如:delegate void MyDel(int n)

    注意:这里除了前面的delegate,剩下部分和声明一个函数一样,但是MyDel不是函数名,而是委托类型名

  3,可以声明一个变量,指向和它类型相容的方法

  4,如何创建委托类型的对象:

    MyDel sp = new MyDel(SayHello);
    注意:
    SayHello需要和MyDel的参数和返回值一样;
    sp这个委托变量就指向SayHello这个方法,不要写成new MyDel(SayHello()),因为加上()就是调用方法了

  5,简化的方法:

    MyDel sp = SayHello;//编译器会给搞成new MyDel(SayHello)

    注意不要写成MyDel sp = SayHello();

  6,委托的使用:

    委托变量之间是可以互相赋值的,就是一个传递指向方法的过程;

    sp()就是调用指向的方法,如果有参数就传递参数

    代码示例:
    public delegate void MyDel(int n);//第一步,声明一个委托

    static void M1(int a)//定义一个方法,方法的参数和返回值要和委托对应
    {
      Console.WriteLine("M1"+a);
    }

    MyDel d1 = new MyDel(M1);//声明一个MyDel类型的变量,指向一个指向M1方法的对象
    //上面的代码可以简化成 MyDel d1 = M1;

    注意:委托是引用类型,可以为null,如果委托变量是null,那么如果调用的话,就会抛出异常:NullReferenceException;

7,Func、Action

  .Net中内置两个泛型委托Func和Action(在“对象浏览器”的mscorlib的System下),日常开发中基本不用自定义委托类型了

  Func是有返回值的委托,Action是没有返回值的委托

8,匿名方法

  使用Delegate的时候很多时候没有必要使用一个普通的方法,因为这个方法只有这个Delegate会用,并且只用一次,这个时候使用匿名方法最合适

  匿名方法就是没有名字的方法

  示例代码:
    MyDelegate p = delegate(int s){s = 10;};

9,lambad表达式
  函数式编程,在EntityFramework编程中用的很多

  1,Action<int> a1 = delegate (int i){Console.Write(i);};

  2, 可以简化为:
    Action<int> a2 = (int i)=>{Console.Write(i);};//(=>读作goes to)

  3,还可以省略参数类型(编译器会自动根据委托类型推断)
    Action<int> a3 = (i)=>{Console.Write(i);};

  4,如果只有一个参数还可以省略参数的小括号(多个参数不行)
    Action<int> a4 = i=>{Console.Write(i);};

5,如果委托有返回值,并且方法体只有一行代码,这一行代码还是返回值,那么久可以连方法的大括号和return都省略

  原本的:Func<int,int,string> f1 = delegate (int i,int j){return "结果是"+(i+j);};

  简化为:Func<int,int,string> f2 = (i,j) =>"结果是"+(i+j);

  普通匿名类型也是一样用lambda表达式

6,委托深入

  集合常用扩展方法:

  Where(支持委托)、Select(支持委托)、Max、Min、OrderBy

  First(获取第一个,如果没有则异常)

  FirstOrDefault(获取第一个,如果一个都没有则返回默认值)

  Single(获取唯一一个,如果没有或者多个则异常)

  SingleOrDefault(获取唯一一个,如果没有则返回默认值,多个则异常)

  ToList、ToArray

7,委托的组合

  委托对象可以“+相加”,调用组合后的新委托对象会一次调用被组合取来的委托:MyDel m5 = m1+m2+m3;

  组合的委托必须是同一个委托类型

  委托的“-”则是从组合委托中把委托移除;

  委托如果有返回值,则有一些特殊。委托的组合一般是给事件用的,用普通的委托的时候很少用

8,事件

  事件语法:event MyDelegate md1;

  加了event关键字实现事件机制的好处:用了event事件,不可以修改事件已经注册的值;不可以冒充进行事件通知了。只能+=、-=

9,委托与事件总结

  委托的作用:
    占位,在不知道将来要执行的方法的具体代码时,可以先用一个委托变量来代替方法调用(委托的返回值,参数列表要明确)。
    在实际调用之前,需要为委托赋值,否则为null

  事件的作用:
    事件的作用与委托变量一样,只是功能上比委托变量有更多的限制。
  比如:
    1,只能通过+=或-=来绑定方法(事件处理程序)
    2,只能在类内部调用(触发)事件

  (面试题)事件和委托的关系:事件由一个私有的委托变量和add_***和remove_***方法组成

  事件的非简化写法:声明一个私有的委托变量和add、remove方法

10,委托和事件的区别和关系

  错误的说法“事件是一种特殊的委托”

  委托用的比较多,事件只有开发WinForm、WPF的时候用的才比较多

  事件、索引器、属性本质上都是方法。

  (面试题)接口中可以定义什么?

  接口中只可以定义方法。接口中可以定义“事件、索引器、属性”,因为他们本质上也都是方法。

十三、反射

  1,反射的作用:动态创建对象、动态赋值、动态调用方法

  2,反射简介

    1,.Net中的类都被编译成IL,反射就可以在运行时获得类的信息(有哪些方法、字段、构造函数、父类是什么等等),
    还可以动态创建对象、调用成员

    2,每个类对应一个Type对象,每个方法对应一个MethodInfo对象,每个属性对应一个PropertyInfo……。
    这些就是类、方法、属性的“元数据”(meta data)。
    对象和这个类的对象没有直接关系。
    这些“元数据对象”和成员有关,和对象无关,也就是每个成员对应一个对象。

  3,类元数据Type

    1,使用写好的Person类
      1,获取类信息对象Type的方法:
        从对象获取:Type type = person.getType();
        从类名获取:Type type =typeof(Person); (type 是关键字,不是方法)
        从全类名(命名空间+类名)获取:Type type = Type.GetType("com.rupeng.Person");

      2,为什么要有这么多获取方式?
        主要根据要查询的内容一样,方式也就不一样。
        如果有一个对象,就用getType()。
        如果没有对象就可以用typeof;
        如果要运行时通过配置文件等拿到的字符串来获取就要用Type.GetType("com.rupeng.Person");

      3,Activator.CreateInstance(type)
        //使用无参数构造方法创建此类的对象(如果没有无参构造函数会报异常)。
        要求类必须有无参构造函数。 相当于new Person() 是闲的蛋疼吗?
    2,父类中GetType()返回的是什么?this代表“当前对象”,不是“当前类”

    3,Type的成员方法

      1,IsInterface、IsArray、IsPrimitive、 IsEnum:是否接口、数组、原始类型、枚举等。

      2,String Name得到类名(不包含命名空间);String FullName包含命名空间

      3,BaseType得到父类的Type。

  4,Type的成员
    1,构造函数
      ConstructorInfo GetConstructor(Type[] types)//获取参数类型匹配的构造函数
      ConstructorInfo[] GetConstructors()//获得所有的public构造函数,包括父类的
      调用object Invoke(object[] parameters)可以调用构造函数

    2,方法
      MethodInfo GetMethod(string name, Type[] types)
      MethodInfo[] GetMethods() //获得所有的public方法
      调用object Invoke(object obj, object[] parameters)可以调用方法

    3,属性
      PropertyInfo GetProperty(string name) 获取某个属性
      PropertyInfo[] GetProperties() 获取所有属性
      PropertyInfo的主要成员:
      CanRead、 CanWrite是否可读写; GetValue、 SetValue读写值(第一个参数是要在哪个对象要调用)

    4,常用的Attribute(特性)
      [Obsolete] 表名此成员已过时

      当使用PropertyGrid的时候可以修饰属性
      [ReadOnly(true)]在编辑器中只读,代码赋值不受影响;
      [DisplayName("姓名")] 属性的显示名;
      [Browsable(false)]属性是否可见

      1,Attribute语法
        Attribute用来在代码中附加一些元信息,这些原信息可被编译器,.NetFramework,或者我们的程序使用。
        方法、属性、类上都可以标注Attribute

        一般起到说明、配置的作用;命名一般以Attribute结尾,如果以Attribute结尾的话使用的时候可以省略Attribute

        注解不会直接影响代码的实际逻辑,仅仅起到辅助性作用;如果起作用也是编译器、.NetFramework、程序去解析的

        在Type、MethodInfo、PropertyInfo等上都可以调用object[] GetCustomAttributes(Type attributeType,bool inherit)获取标注的注解对象
        因为同一个Attribute可能标注多次,所以返回值是数组


十四、正则表达式

  1,正则表达式是对字符串进行匹配的语法,用来判断一个字符串是否符合某个规则

  2,基本元字符:

    a,. 表示除了\n以外的任意的单个字符

    b,[0-9]表示的是0-9之间的任意一个整数数字;[a-z]任意一个小写字母;[A-Z]任意一个大写字母

    c,\d 表示数字,\D表示非数字,\s表示空白,\S表示非空白,\w表示小写字母或数字和汉字
      \W表示特殊符号

    d,\ 表示对于 . 等特殊字符转义

    e,()提升优先级别和提取组

    f,[]代表一个区间中的任意一个:[abc\d]就代表abc或者数字中的任意一个字符

    g,| 代表或者

    h,+ 是出现1次或者无限次

    i,* 是出现0次或者无限次

    j,? 是出现0次或者1次

    k,{5}出现5次,{1,2}出现一次或者两次,{5,8}出现5次至8次,

      {1,}最少出现1次,{3,}最少出现3次
    l,^ 以。。开始;$以。。结束

    使用Regex.isMatch("目标字符串",@"正则表达式");//返回值是bool类型

    提取://使用()进行分组,然后调用match.Groups[0].Value进行取值
      Match match = Regex.Match("2016-12-29", @"^(\d{4})\-(\d{1,2})\-(\d{1,2})$");

    示例代码:

      Console.WriteLine( Regex.IsMatch("2016-12-29", @"^\d{4}\-\d{1,2}\-\d{1,2}$") );

      Match match = Regex.Match("2016-12-29", @"^(\d{4})\-(\d{1,2})\-(\d{1,2})$");
      if (match.Success)
      {
        string year = match.Groups[0].Value;
        string month = match.Groups[1].Value;
        string day = match.Groups[2].Value;
        Console.WriteLine("年"+year+"月"+month+"日"+day);
      }
      else
      {
        Console.WriteLine("匹配不成功");
      }
      Console.ReadKey();

十五、对象的序列化

    对象序列化是将对象转换成为二进制数据(字节流),反序列化是将其还原为对象。

    用处,避免程序重启等情况造成的数据丢失,不仅程序重启、操作系统重启会造成对象的消失,就连退出函数范围等都可能造成对象的消失

    序列化和反序列化就是为了保持对象的持久化

    注意:一个对象想能序列化,必须标注成[Serializable],其父类和相关的字段、属性都要标记成“可序列化”

    序列化只会对类中的字段序列化(只序列化一些状态信息)

    类结构改变后,之前序列化的内容尽量不用,否则可能会出错!

    使用:
      BinaryFormatter类有两个方法:
      void Serialize(Stream stream, object pbj)

      对象obj序列化到Stream中
      object Deserialize(Stream stream)
      将对象从stream中反序列化,返回值为反序列化得到的对象

    为什么要序列化:
      保持对象的持久化,将一个复杂的对象转换流,方便我们的存储与信息交换

    应用:
      Asp.net中进程外Session要求对象可序列化
      还有Xml序列化,应用开发中Json序列化已经代替了二进制序列化和Xml序列化等


十六、XML(可扩展标记语言)

  1,XML优点:
    容易读懂;格式标准任何语言都内置了XML分析引擎,不用单独进行文件分析引擎的编写

  2,是一种格式化的方式来存储数据,可以用记事本、浏览器打开

  3,.Net程序中的一些配置文件app.config、web.config文件都是xml文件

  4,语法规范:
    标签/节点(Tag/Node)、嵌套(Nest)、属性。标签要闭合,属性值要用“”包围,标签可以互相嵌套

    XML树,父节点、子节点、兄弟节点(siblings)

    xml编写完成以后可以用浏览器来查看,如果写错了浏览器会提示。如果明明没错,浏览器还是提示错误,则可能是文件编码问题。

  5,语法特点:
    严格区分大小写;

    有且只有一个根节点

    有开始标签必须有结束标签,除非自闭和(没有内容的时候)<Person/>

    属性必须使用双引号
      (可写可不写,写了文件类型的时候要注意实际保存的文件类型需要一致)

    文档声明:
      <?xml version="1.0" encodeing="utf-8"?>

    注释:

      <!--要注释的内容-->


  6,注意编码问题,文本文件实际编码与文档声明中的编码一致

  7,读取xml文件:
    <Person>
      <Student StuID="11">
        <StuName>张三</StuName>
      </Student>
      <Student StuID="22">
        <StuName>李四</StuName>
      </Student>
    </Person>


    XmlDocument doc = new XmlDocument();//创建一个读取器对象
    doc.Load(@"xml文件的路径");//加载xml文件
    XmlNodeList students = doc.DocumentElement.ChildNodes;//拿到xml文件的节点集合
    foreach(XmlNode stu int students)
    {
      XmlElement element = (XmlElement)stu;
      string stuId = element.GetAttribute("StuID");
      XmlNode nameNode = element.SelectSingleNode("StuName");//获取Person接线的Name
      string name = nameNode.innerText;
      Console.WriteLine(stuId+","+name);
    }

  8,生成XML文件

    XmlDocument doc = new XmlDocument();//创建XML文件对象
    XmlElement ePersons = doc.CreateElement("Persons");//创建根节点对象
    doc.AppendChild(ePersons);//将根节点对象添加到XML文件对象
    foreach(Person person in ePersons)
    {
      XmlElement ePerson = doc.CreateElement("Person");
      ePerson.SetAttribute("id",person.id.ToString());
      XmlElement eName = doc.CreateElement("Name");
      eName.InnerText = person.Name;
      XmlElement eAge = doc.CreateElement("Age");
      eAge.InnerText = person.Age.ToString();

      ePerson.AppendChild(eName);//给ePerson添加子节点eName
      ePerson.AppendChild(eAge);//给ePerson添加子节点eAge
      ePersons.AppendChild(ePerson);//将ePerson添加给根节点
    }
    doc.Save("文件全路径");



    class Person
    {
      public Person(int id, string name, int age)
      {
        this.Id = id;
        this.Name = name;
        this.Age = age;
      }
      public int Id { set; get; }
      public string Name { set; get; }
      public int Age { set; get; }
    }

    Person[] persons = { new Person(1, "rupeng", 8), new Person(2, "baidu", 6) };

 

如鹏网学习笔记(三).Net高级技术

标签:param   har   笔记   over   序列化   exception   get   元数据   组合   

原文地址:http://www.cnblogs.com/DotNetStu/p/7396886.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!