Bootstrap

.NET 知识点(持续更新)

目录

  • .NET 知识点
    • C#
      • Hashtable 和 Dictionary <K, V> 类型
    • GC(垃圾回收机制)算法
      • 公共语言运行库 (common language runtime,CLR)
      • C#中堆和栈的区别?
      • 引用类型
      • C#中的委托是什么?事件是不是一种委托?
      • C#中什么是值类型与引用类型?
      • 请详述在C#中类(class)与结构(struct)的异同?
      • int?和int有什么区别
      • C#中参数传递 ref 与 out 的区别?
      • C#中什么是装箱和拆箱?
      • C#实现多态的过程中 overload 重载 与override 重写的区别?
      • C# 中 static 关键字的作用?
      • C#中抽象类和接口有什么区别?
      • C#中用sealed修饰的类有什么特点?
      • 特性是什么?如何使用?
      • 面向对象的主要思想:继承、封装、多态
    • 数据库
      • 数据库范式
      • 存储过程
      • 视图
      • 什么是锁?
      • 触发器
      • 事务特性

.NET 知识点

C#

Hashtable 和 Dictionary <K, V> 类型

  1. 单线程程序中推荐使用 Dictionary, 有泛型优势, 且读取速度较快, 容量利用更充分.
  2. 多线程程序中推荐使用 Hashtable, 默认的 Hashtable 允许单线程写入, 多线程读取, 对 Hashtable 进一步调用 Synchronized()方法可以获得完全线程安全的类型. 而Dictionary 非线程安全, 必须人为使用 lock 语句进行保护, 效率大减.
  3. Dictionary 有按插入顺序排列数据的特性 (注: 但当调用 Remove() 删除过节点后顺序被打乱), 因此在需要体现顺序的情境中使用 Dictionary 能获得一定方便.

GC(垃圾回收机制)算法

  1. 标记压缩算法:阶段1: Mark-Sweep 标记清除阶段,先假设堆中所有对象都可以回收,然后找出不能回收的对象,给这些对象打上标记,最后堆中没有打标记的对象都是可以被回收的;阶段2: Compact 压缩阶段,对象回收之后堆内存空间变得不连续,在堆中移动这些对象,使他们重新从堆基地址开始连续排列,类似于磁盘空间的碎片整理;
  2. 分代算法:CLR初始化后的第一批被创建的对象被列为0代对象。CLR会为0代对象设定一个容量限制,当创建的对象大小超过这个设定的容量上限时,GC就会开始工作,工作的范围是0代对象所处的内存区域,然后开始搜寻垃圾对象,并释放内存。当GC工作结束后,幸存的对象将被列为第1代对象而保留在第1代对象的区域内。此后新创建的对象将被列为新的一批0代对象,直到0代的内存区域再次被填满,然后会针对0代对象区域进行新一轮的垃圾收集,之后这些0代对象又会列为第1代对象,并入第1代区域内。第1代区域起初也会被设上一个容量限制值,等到第1代对象大小超过了这个限制之后,GC就会扩大战场,对第1代区域也做一次垃圾收集,之后,又一次幸存下来的对象将会提升一个代龄,成为第2代对象。

公共语言运行库 (common language runtime,CLR)

公共语言运行库是托管代码执行核心中的引擎;负责应用程序在整个执行期间的代码管理工作,比较典型的有:内存管理、线程管理、安全管理、远程管理、即时编译、代码强制安全类检查等;

C#中堆和栈的区别?

  1. 栈:由编译器自动分配、释放。在函数体中定义的变量通常在栈上。存放在栈中时要管存储顺序,保持着先进后出的原则,他是一片连续的内存域,有系统自动分配和维护;
  2. 堆:一般由程序员分配释放。用 new、 malloc 等分配内存函数分配得到的就是在堆上。是无序的,他是一片不连续的内存域,有用户自己来控制和释放,如果用户自己不释放的话,当内存达到一定的特定值时,通过垃圾回收器(GC) 来回收。
  3. 栈内存无需我们管理,也不受 GC 管理。当栈顶元素使用完毕,立马释放。而堆则需要 GC 清理。

引用类型

使用引用类型的时候,一般是对指针进行的操作而非引用类型对象本身。但是值类型则操作其本身。

C#中的委托是什么?事件是不是一种委托?

委托的本质是一个类,委托是将一种方法作为参数代入到另一种方法。事件是委托的实例,事件是一种特殊的委托。// 比如:onclick 事件中的参数就是一种方法。

C#中什么是值类型与引用类型?

值类型:struct 、 enum 、 int 、 float 、 char 、 bool 、 decimal
引用类型:class 、 delegate 、 interface 、 array 、 object 、 string

请详述在C#中类(class)与结构(struct)的异同?

class 可以被实例化 , 属于引用类型 ,
class 可以实现接口和单继承其他类 , 还可以作为基类型 , 是分配在内存的堆上的
struct 属于值类型 , 不能作为基类型 , 但是可以实现接口 , 是分配在内存的栈上的。

int?和int有什么区别

int ?为可空类型,默认值可以是 null
int 默认值是 0
int? 是通过 int 装箱为引用类型实现。

C#中参数传递 ref 与 out 的区别?

( 1 ) ref 指定的参数在函数调用时必须先初始化,而 out 不用;
( 2 ) out 指定的参数在进入函数时会清空自己,因此必须在函数内部进行初始化赋值操作,而 ref 不用;
总结:ref 可以把值传到方法里,也可以把值传到方法外;out 只可以把值传到方法外
注意:string 作为特殊的引用类型,其操作是与值类型看齐的,若要将方法内对形参赋值后的结果传递出来,需要加上ref 或 out 关键字。

C#中什么是装箱和拆箱?

  1. 装箱:把值类型转换成引用类型
  2. 拆箱:把引用类型转换成值类型
  3. 装箱:对值类型在堆中分配一个对象实例,并将该值复制到新的对象中。
    • 第一步:新分配托管堆内存 ( 大小为值类型实例大小加上一个方法表指针。
    • 第二步:将值类型的实例字段拷贝到新分配的内存中。
    • 第三步:返回托管堆中新分配对象的地址。这个地址就是一个指向对象的引用了。
  4. 拆箱:检查对象实例,确保它是给定值类型的一个装箱值。将该值从实例复制到值类型变量中。
    在装箱时是不需要显式的类型转换的,不过拆箱需要显式的类型转换。

C#实现多态的过程中 overload 重载 与override 重写的区别?

  1. 定义不同:重载是定义相同的方法名、参数不同,重写是子类重写父类的方法
  2. 范围不同:重载是在一个类中,重写是子类与父类之间的
  3. 多态不同:重载是编译时的多态性,重写是运行时的多态性
  4. 参数不同:重载的参数个数、参数类型、参数的顺序可以不同,重写父类子方法参数必须相同
  5. 修饰不同:重载对修饰范围没有要求,重写要求重写方法的修饰范围大于被重写方法的修饰范围;

C# 中 static 关键字的作用?

  • 修饰静态类和成员(静态字段和方法),访问时直接通过类访问;
  • 静态类不可实例化,只能包含静态成员;
  • 不可包含构造函数,可包含静态构造函数,
  • 静态构造函数不可被调用,只在类被加载是自动执行一次;

C#中抽象类和接口有什么区别?

  • 抽象类可以声明抽象类抽象方法,一个类中有抽象方法,那么这个类就是抽象类。
  • 抽象方法,就是不含主体(不提供实现方法),必须由继承者重写。因此,抽象类不可实例化;
  • 接口只提供一些方法规约,在 C#8 之前的版本中不提供任何实现,在 C#9 版本也可以支持接口的实现;不能用public 、 abstract 等修饰,无字段、常量,无构造函数;
  • 两者区别:
    1. 接口中不能有字段,而抽象类可以有;
    2. 接口中不能有 public 等修饰符,而抽象类可以有;
    3. 接口可以实现多继承,抽象类只可以单继承;

C#中用sealed修饰的类有什么特点?

密封,不能继承。

特性是什么?如何使用?

关联的目标对象的附加信息;

面向对象的主要思想:继承、封装、多态

数据库

数据库范式

  1. 第一范式:强调属性的原子性约束,要求属性具有原子性,不可再分解。
    • 举例:一个地址字段,可以细分为国家、省份、城市、市区、街道;
  2. 第二范式:强调记录的唯一性约束,数据表必须有一个主键,并且没有包含在主键中的列必须完全依赖于主键,而不能只依赖于主键的一部分。
    • 举例:库存表(仓库编码,产品编码,产品名称),其中主键是(仓库编码,产品编码),产品名称只依赖于产品编码。存在部分依赖。可以改造成两个表:库存表(仓库编码,产品编码)和产品表(产品编码,产品名称)
  3. 第三范式:强调数据属性冗余性的约束,非主键列必须直接依赖于主键。
    • 举例:调查点表(点编号,调查人,调查单位)
    • BCNF(巴克斯范式):属于修正的第三范式,是防止主键的某一列会依赖于主键的其他列。
    • 举例:假设仓库管理关系表(仓库ID,存储物品ID,管理员ID,数量),一个管理员只在一个仓库工作;一个仓库可以存储多种物品。这个数据库表中存在如下决定关系:
        (仓库ID,存储物品ID) →(管理员ID,数量)
        (管理员ID,存储物品ID) → (仓库ID,数量)
        所以,(仓库ID,存储物品ID)和(管理员ID,存储物品ID)都是StorehouseManage的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:
        (仓库ID) → (管理员ID)
        (管理员ID) → (仓库ID)
      (1) 删除异常:当仓库被清空后,所有"存储物品ID"和"数量"信息被删除的同时,"仓库ID"和"管理员ID"信息也被删除了。
      (2) 插入异常:当仓库没有存储任何物品时,无法给仓库分配管理员。
      (3) 更新异常:如果仓库换了管理员,则表中所有行的管理员ID都要修改。
  4. 第四范式:非主属性不应该有多值。如果有多值就违反了第四范式。4NF是限制关系模式的属性间不允许有非平凡且非函数依赖的多值依赖。
    • 举例:用户联系方式表(用户id,固定电话,移动电话),其中用户id是主键,这个满足了BCNF,但是一个用户有可能会有多个固定电话或者多个移动电话,那么这种设计就不合理,应该改为(用户id,联系方式类型,电话号码)
  5. 第五范式:
    (1)必须满足第四范式
    (2)表必须可以分解为较小的表,除非那些表在逻辑上拥有与原始表相同的主键。
    • 举例: 调查记录表:调查点,调查人,工作区,调查时间 ——调查点,工作区 调查点、调查人,调查时间

存储过程

存储过程是经过编译并存储在数据库中的一段SQL语句的集合。

  • 优点:
    1. 简化了复杂的操作,每次使用直接调用就可以了;
    2. 减少应用程序和数据库服务器之间的流量,不必每次发送整个逻辑的SQL语句;
    3. 可重复使用,所有连接数据库的应用程序都可以调用;
    4. 权限分配时,可以只给存储过程的访问权限,不需要每张表的访问权限,有一定的安全性;
  • 缺点:
    1. 数据库设计侧重于高效的查询,而不是逻辑运算,大量的存储过程会影响数据库运行效率;
    2. 存储过程编写过程中无法调试;
    3. 移植性差;

视图

视图是一种虚拟存在的表,是一个逻辑表,本身并不包含数据。作为一个select语句保存在数据字典中的。(简单:不需要关心后面对应的表的结构、关联条件和筛选条件;安全:用户只能访问他们被允许查询的结果集;数据独立:一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。)

什么是锁?

锁是在多用户环境中堆数据访问的限制;
脏读:事务并发查询造成,A事务未提交时,B事务读取数据,A事务回滚,B事务读的就是脏数据;
丢失更新:A事务和B事务同时读取同一数据,并对数据进行更新,先提交的事务就会被后提交事务覆盖;
不可重复读:不可重复读出现的原因就是事务并发修改记录;A事务读取数据后,B事务对数据进行修改并提交,A数据按照最先读取的数据进行操作就会出现错误;(要避免这种情况,最简单的方法就是对要修改的记录加锁,但会导致锁竞争加剧,影响性能。)
幻读:幻读是由于并发事务增加记录导致的,A事务读取表数据后,B事务向表中添加一条记录,A再次读取表数据就会多出一条记录(这个不能像不可重复读通过记录加锁解决,因为对于新增的记录根本无法加锁。需要将事务串行化,才能避免幻读。)

触发器

触发器(trigger)是一种特殊的存储过程,不需要调用,当对数据库表中的数据执行DML操作时自动触发这个SQL片段的执行,无需手动调用。

  1. 可以自动执行。触发器在对表的数据作了任何修改(比如手工输入或者应用程序的操作)之后立即被激活。
  2. 可以级联更新。触发器可以通过数据库中的相关表进行层叠更改,这比直接把代码写在前台的做法更安全合理。
  3. 可以强化约束。触发器可以引用其它表中的列,能够实现比CHECK约束更为复杂的约束。
  4. 可以跟踪变化。触发器可以阻止数据库中未经许可的指定更新和变化。5. 强制业务逻辑。触发器可用于执行管理任务,并强制影响数据库的复杂业务规则。

事务特性

  1. 原子性:事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
  2. 一致性: 确保从一个正确的状态转换到另外一个正确的状态,这就是一致性。例如付款过程中,付款方余额减少,收款方余额增加,中间出现了错误导致间断,付款成功,但是收款失败,这就违反了一致性。又比如表更新事务,一部分数据更新了,但一部分数据没有更新,也是违反一致性的;
  3. 隔离性:并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
  4. 持久性:一个事务被提交之后,对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
;