.Net的基础概念

  • 1,参数传递.

默认都是按值传递(无论引用还是值类型),也就意味着传递参数的一个副本给方法.之后在方法体内对参数的更改,对原始参数没有影响.

使用ref/out可以按引用传递,直接影响原始参数变量.两者的区别是ref参数必须在传递之前进行初始化.在异步方法和迭代器方法中,不能使用它.

2,CTS,CLS

CTS是一个集合,符合它的规范的类型才能在CLR上运行.CLS是它的子集,因为C#中有的类型,在VB中可能没有(ulong).

默认不会进行CLS的检查,[assembly:System.CLSCompliant(true)]可以进行检查.

不符合CLS的代码,在不同语言间会出现复用的问题.

3,CLR

编译阶段,生成的是CIL组成的中间语言,然后在运行时由个平台的JIT来编译成机器指令进行运行,所以能够跨平台.

作用:1)管理内存(处理对象布局,管理对象引用,自动GC),2)线程执行,3)代码执行(可与非托管代码互操作,引用COM DLL),4)代码安全验证(取决于组件的来源)(以CTS验证Type),5)编译(CLR从不解释托管代码,由JIT编译代码),其可由高性能Server App承载并用托管代码编写逻辑.

4,GC

0代是新创建的对象,1代是经历过1次GC后留存的,2代是经历过1次以上GC留存的.回收时,先从0代开始.

5,is/as

  • is.如果被判断对象是null,那么返回false.
  • as.如果类型不兼容,那么返回null.
  • 两者都不会抛出异常.但是as更加高效.

6,接口/抽象类

  • 接口.不能含有Field和静态成员.可以作用于引用和值类型.
  • 抽象类.不能被new,不能sealed.实现其方法是用overriding.
  • "接口不变".当新增功能时,不能修改旧接口,而应该添加新的接口.接口应该设计为单一功能.
  • 当组件要被设计为多个版本时,是用抽象类.
  • 当功能要被使用在大范围的全异对象上时,使用接口.抽象类用于关系紧密的对象组.
  • 接口更适合于小而简练的功能.而抽象类可以有默认的实现.
  • 对于一个继承了多个接口的类,而多个接口中含有相同签名的方法,只需要实现一次即可.当需要分别实现时,必须显示指定,并且调用时需要类型转换.

7,Attribute特性

  • 本质上是Class,为目标元素提供关联附加信息.在运行时通过反射来获取该附加信息,来动态改变代码的执行方式.
  • 主要用于序列化,编译器指令,设计模式上.
  • 其实例在编译时初始化.
  • 所有特性都继承自System.Attribute.必须有公用的构造器.特性还可以应用到其他特性上.

8,Struct

  • 继承自System.ValueType(该类型为Ref类型),不具备多态性。
  • 值类型,存储在堆栈上.
  • 常用于存储数据。没有继承性。只能实现接口。
  • 只能定义带参构造器,不能有解析器,也不能有自定义无参构造(因为默认含有无参的Public构造).
  • 其可以不使用New初始化,但这样的话所有的字段都是未初始化状态,直到所有字段都完成初始化,否则引用它就会编译错误.
  • 可以重载Object的3个方法:Equals,ToString,GetHashTable.
  • struct变量使用完后,自动解除内存分配.
  • 用途:主要用于存储数据时,当数据量小时,结构数组有更高的效率,提供和非托管代码兼容性.

9,CTS

  • 目的是创建一个跨语言的,类型安全,高性能代码执行的框架.定义各个语言必须遵守的规则,以使得使用不同语言建立的对象能够进行交互.
  • CTS定义了MSIL使用的预定义类型.所有的.NET编译器都是基于CTS实现的,因为所有的程序最后都要被编译成IL.
  • CLS是CTS的子集,定义了面向.NET的开发语言所必须支持的最小集合.
  • CIL,IL定义了与机器无关的虚拟指令.在执行时IL会被翻译成本地代码.
  • .Net Framework可以看做CIL在Win平台下的实现.

10,参数

  • ref/out
    • 方法的定义和调用都需要有该keyword.否则编译错误.
    • 允许是否使用该keyword而带来的方法重载,而不能在两者之间进行.因为两者在编译后生成的IL代码是相同的.
    • ref传递的必须是一个初始化过的实际对象.
    • out可以接受null参数,但是在方法返回之前,必须进行赋值.同时,方法体内,会将外界赋给参数的值清空.
  • 按值/引用传递参数
    • 按值传递.引用类型传递的是该引用的值,即对象的地址.值类型传递的是该值的一个副本,所以修改参数的值不会影响原值.
    • 按引用传递.引用/值类型传递的都是引用/值的地址.

11,委托

  • 存放着对方法引用的引用类型.
  • 可在全局范围内定义.
  • 应用了策略模式.把变化的部分封装起来.然后再把封装的对象作为一个对象传递给方法作为参数.
  • 实际上是一个类,可以使用new来实例化生成对象.定义了方法的类型.
  • 允许把方法当做另一方法的参数来传递.
  • 分离了方法的声明和方法的实现.
  • 把对方法的引用封装在委托对象中.
  • 调用时,用一个委托对象的变量来替代方法名称.
  • 内部继承关系:MultiDelegate->Delegate.
  • 字段:_target(方法所在类的对象,静态方法时为null)._MethodPtr(标识要调用的方法)._invocationList(委托链).
  • 委托链也是委托.可进行的操作是+=/-=.使用GetInvocationList()来获取委托链.
  • 事件就是一种委托链.

Other

  • 枚举打印(toString)时,输出的是成员名称,而非1,2,3.
  • 类只能通过引用存储它的堆来访问.对引用赋值,只会创建引用的副本,而非实例的副本,然后所有的引用都指向同一存储区.
  • 可以使用Using来简化引用命名空间时的字符数.Using print= System.Consle.
  • 异常
    • 当没有Catch语句时,执行到Finally后停止,之后的代码会被忽略.
    • 有catch时,会执行完try-catch-finally,然后执行之后的代码.
    • throw Exception之后的代码不会被执行.
  • Box
    • 装箱是隐式发生的.
    • 而拆箱必须显式进行,并且类型要相同,兼容也不行.
  • 调用Windows API函数.

    • 引用System.Runtime.InterpServices;[DllImport(“XX”,Entry Point=”XXX”,CharSet=”XXXX”)]:XX为Dll所在的位置(User32.dll);XXX为所要引用的函数名,XXXX=UniCode/ANSI.

  • 继承
    • 子类使用new来覆盖父类的同名方法,然后再使用base.FunName()来调用被覆盖的父类方法.
  • 泛型
    • CLR允许值,引用,接口,委托的泛型,不支持枚举泛型.
    • CLR保证泛型并识别泛型的类型安全,并且不会产生拆箱,装箱动作.
    • 编译时T是一个占位符.实例化时根据不同的传入类型进行替换.
    • 不同的类型生成不同的代码(Class).各个类之间没有关系.
    • 静态变量在不同类型的Class之间不会共享.
    • 重载方法.在实例方法调用时检查(而非编译时).当一般方法与泛型方法签名相同时,一般方法优先.
    • 将泛型变量转换为另一类型为非法.除非另一类型兼容约束,可先转化为Object后在进行该转换;在没有约束类型为引用时,将泛型类型转化为NULL为非法.可指定默认值;与NULL比较,当无约束时可正常运行,但是当约束为Struct时,编译错误;未约束为引用时,对两个变量的比较为非法;不可将+,-*应用于非约束泛型类型上.
    • <T>类型参数(占位符);<int>类型实参.
    • 开放类型:含有<T>的;封闭类型:每个参数都是<int>的.只能构造封闭类型的instance.
    • ArrayList由于会产生装箱/拆箱操作,所以性能不如List<T>.
    • 类型推断
      • 在调用泛型方法时,自动判断所使用的类型.
      • 依据是变量的Type,而非引用的Type.所以是一种编译时行为.
    • 协变/逆变
      • 协变:子类到父类;逆变:父类到子类.
      • 仅泛型接口和委托支持,泛型类和方法不支持.
      • 原则:若一个几口需要对T支持协/逆变,则该接口所有的方法参数必须支持对T的协/逆变.
  • 迭代器
    • foreach可以用于任何实现了IEnumerator GetEnumerator()方法的类上,而不必非要实现IEnumerable接口.
    • 1  public IEnumerator<int> GetEnumerator()
      2         {
      3             int[] list = new int[]{1,2,3};
      4             foreach (int i in list)
      5                 yield return i;
      6         }
      GetEnumerator
    • yeild return 语句会使得Complier隐式生成一个实现了IEnumerable接口的内部类.
    • foreach的调用流程:GetEnumerator()->MoveNext()->return .Current.
    • 迭代器是延迟加载的,到in语句时才会调用.
  • If (o is Employee){Employee e = (Employee)o}两次转换;Employee e = o as Employee; If(e ! Null )一次,而且永不抛出异常.
  • Static常量直接嵌入IL内,无内存及地址,仅可为值类型(创建Type对象时创建,在类被夹在到AppDomain时创建).字段基于引用,ReadOnly(不可变的引用,而非不可变的对象)只可在构造器内为可写,其余只可读.不支持常量方法/参数.
  • 值类型[],New时会创建Obejct=0;引用类型[],New会创建引用,而无实际的元素对象.
  • 消息队列(MSMQ)
    • OS通信的基础(NT,2000以上),用于创建分布式,松散连接通信APP这些APP可通过不同种类的网络通信,亦可脱机.向断开连接的队列发送信息和有连接时一样.
    • 用户队列:公用MSMQ:在所有网络上复制传输,可被所有站点访问;专用MSMQ:仅在锁驻留的本地PC上可用(只能当知道完整Path或检查的APP访问),管理MSMQ:指定希望队列组件使用的管理的.响应MSMQ:目标APP接到消息返回给发送APP的相应信息.
    • 系统队列:日记:可选地存储,发送消息副本和删除信息;死信:存放无法传递或已过期的消息副本;专用系统:一系列系统执行处理操作所需的管理和通知消息的专用MSMQ.
    • 用途:1)数据库通过发送Message来操作数据(节省:对数据库连接请求数据的事件,从数据库返回数据的事件),当客户端不需要知道数据库操作结果时;2)ERP:断开连接时保存信息,连接恢复时发送消息,当队列驻留的PC无法工作,或者路由所需域控制器无法工作时消息无法投递,MSMQ可使消息暂存.
    • 由于消息传输时占用大量的带宽.所以应该尽量少使用.
  • 序列化
    • 可以利用序列化技术创建对象的深拷贝.
    • 必须保证序列化/反序列化时使用相同的formatter.
    • 可以将多个对象序列化到一个Stream中,然后以相同的顺序从Stream中反序列化出各个对象.
    • 序列化一个对象时,Type的全名和Assembly名会写入流中.
    • 反序列化时,使用Assembly.load方法加载Assembly.
    • 枚举和委托类型总是可序列化的.
    • 父类可序列化,子类必须显示声明才可以被序列化.
      • 子类为可序列化,而父类不可,那么结果亦是不可.
      • Object类是可序列化的.
      • 序列化会读取一个对象的所有字段(包括private).
      • 如果类型含有敏感信息,应该设置为不可序列化的.
    • [NoSerialized]标识不被序列化的属性.
    • [Seralizable]标识的属性不应使用自动属性,因为其名称不定.
  • JSON
    • 从结构上看,Data可分解为3个部分
      • Scalar标量.一个单独的字符串或者数字.
      • Sequence序列.有序的若干相关数据并在一起,即数组.
      • Mapping映射.名/值对.又称字典.
    • JOSN定义.
      • 逗号,并列的数据.
      • 冒号:映射.
      • 方括号[].并列数据的集合(数据).
      • 大括号{}.映射的集合(对象).
原文地址:https://www.cnblogs.com/robyn/p/3729372.html