零散知识点
1.值类型和引用类型的区别
- 值类型的变量赋值时是将真实数据的副本付给变量,而引用类型则是将对象的引用付给变量, 这会产生多个多个变量同时指向一个对象实例
- 值类型定义时,会在堆栈上分配内存,引用类型会在堆上分配内存
- 所有的值类型都有共同的基类:System.ValueType.所有值类型都已经实现了类容的比较equals() 方法,而引用类型在没有重写Equals()方法的情况下,任然采用引用比较。
2. 堆和栈的区别
- 栈由操作系统自动分配和释放,一般用于存放函数的参数和局部变量的值。堆有程序员分配和释放,如果程序不主动释放,可在GC进行回收,或在程序结束后由操作系统回收。
- 栈使用的是一级缓存,在调用时被分配空间,调用完毕立即释放;
堆使用的是二级缓存,生命周期由垃圾回收算法来决定。
3.结构和类的区别
- 结构是值类型,类是引用类型 。
- 结构里的成员都是public,类有其他的访问限定符
- 类是显示实物的一种抽象,结构包含不同类别数据的一种包装。所有类型只包含一些数据时,用结构比较合适。
- 结构不能继承,类可以。
- Sealed修饰类有什么特点
Sealed修饰类,表示该类为密封类。不能从它派生出其它类。所有sealed和abstract不能同时限定类
6.结构不能定义不带参数的构造函数,类可以。因为运行库会提供隐式构造方法,把值类型初始成0,把引用类型初始成null.即使提供了带参数的构造函数,也不能绕过默认构造函数;
7.结构不能直接给字段附默认值;
4. 类的访问限定符
Partial: 类分成两个文件,分别在不同的文件中
Public : 该类的访问不受限制。
Internal:同一个assembly的文件间的才可引用,常见的用途是基于组件的开发。
成员的访问限定符
Public:访问不受限制
Private:只能在本类中访问
Protected:在本类或其子类中可以访问
Internal:同一程序集中
6、面向对象的3个基本特征
- 封装:把客观的事物封装成抽象的类,类可以吧自己的数据和方法公开给可信的类或对象进行使用,对不可信的进行信息隐藏;
- 继承:
- 多态:有重载和覆盖两种,覆盖是重写父类在方法。重载是相同方法名,不同参数或返回值。
7.。net托管资源与非托管资源
托管资源:就是由clr分配和释放 的资源,有两种类型,一是普通托管,如int,float等值类型对象;二是非普通托管资源,继承了IDISPOSE接口在类的实例对象。此类资源在被GC回收时要经历两步,会降低系统性能,因此在实现dispose方法时要注意手动清理。
非委托资源:就是不受clr管理的对象。如windows内核对象,File,dbConnection,Socket,com对象等。
继承Idispose接口的类的对象不是非委托 资源,非委托资源无法在程序中自定义。
如果在程序中使用到了非委托资源就要在程序中显示地释放资源,方法是让类型继承Idispose接口,
//自定义非普通托管资源 Class MyResource:IDispose { Public void Dispose(){} } Public class SampleClass :IDispose { //非普通托管资源 MyResource myResource=new MyResource(); //非委托资源 Private IntPtr nativeResource=Marshal.AllocHGlobal(100); //普通委托资源 Private String name=”bany”; Private bool disposed=false; Public void Dispose() { //必须为true,显示释放所有资 源 Dispose(true); //通知垃圾回收机制不再调用终结器(析构器),也就是GC不再调用 ~SampleClass() GC.SuppressFinalize(this); } //防止程序员显示调用dispose()来回收资源,这时可由GC来回收并释放非托管资源。 //析构函数中不允许释放托管资源,因为Gc在调用析构函数前可能已经释放非托管资源 ~SampleClass() { //必须为false Dispose(false); } //如果子类继承并实现了自己的dispose方法,必须调用父类的dispose() 来释放父类中的资源。调用 base.Dispose(disposing); Protected virtual void Dispose(bool disposing) { If(disposed) return ; If(disposing) { //清理非普通类型的托管资源 If(nyResource!=null) { myResource.Dispose(); myResource=null; } } //清理非托管资源 If(nativeResource!=IntPtr.Zero) { Marshal.FreeHGlobal(nativeResource); nativeResource=IntPtr.Zero; } Disposed=true; } }
8. 抽象类和接口
相同点:
1.都不能被实例化;
2.都包含的未实现的方法;
3. 派生类必须要实现未实现的方法,接口是所有定义的方法,抽象类是未定义的方法;
4.他们都是实现扩展的一个手段。
不同点:
1.抽象类是对类的不可变行为的抽象,这些修为可以在抽象类中定义和实现。接口是定义的一组行为规范,不能有实现和私有字段。
2.一个类可以实现多个接口,但只能扩展一个父类。
3.接口不具备继承的任何特点,只承诺能被调用的方法。
4.如果抽象类实现接口,可以将接口的方法映射到抽象方法而不必实现,让子类去实现。
抽象类和接口的使用:
1.尽量避免使用继承来实现组建功能,而是用黑箱复用,即对象组合(把另一个类的对象组合到类中来实现功能组合);
2.接口污染:接口应具备专一功能性,而不是多功能的;
3.oop原则:把可变的和不可变的分离;抽象类和接口都是定义不可变的。
4.如果创建的功能是在大范围的全异对象间使用,则使用接口;
5.如果要设计大的功能单元,则用抽象类,如果在所有实现间提供通用的功能实现,则用接口。
6.抽象类主要用于关系密切的对象; 接口用于为不相关的类提供通用功能;
9.类的设计原则
- 开闭原则:在扩展方面开放,在修改方面封闭。多用接口、抽象类、多态等技术来设计。
实现方法:把不变的部分抽象成接口;
接口要注意最小功能实现;
模块之间的调用要通过接口进行,这样即使实现层发生变化,也无需修改调用层的代码;
2.替换原则:子类可以替换父类,并出现在父类出现的任何地方。
3.依赖原则:依赖关系尽量依赖接口和抽象类。具体类只负责业务实现,修改具体类不会影响整个业务的依赖关系。
高层模块不应该依赖于低层模块,二者都应该依赖于抽象。
抽象不应该依赖于细节,细节应该依赖于抽象
4. 接口分离原则:使用多个专门的接口要比使用单一接口涵盖多个功能好。
5.单一职责:类在。一个操作类只完成一种职责。
设计时如何划分职责:可分为实体类,操作类,边界类;
一种职责:引起该类发生变化的一个原因;
操作类:控制类有效将业务逻辑独立于实体数据和边界控制,专注于处理业务逻辑,控制类会将特有的操作和实体类分离,者有利于实体类的统一化和提高复用性。
10. 静态类和静态构造函数
静态类:该类包含的所有属性和方法都是静态的,该类就是静态类,不能创建静态类的实例,所以不存在构造函数。使用静态类可以检查用户是否不经意的创建的类 的实例。在功能上与使用私有静态构造函数创建的类相同。
构造函数:1.编译器会给没有定义构造函数的类创建默认的不带参数的构造函数,它只能把所有的字段成员初始化为标准的默认值。
2.如果类已提供了带参数的构造函数,编译器就会不自动提供默认的构造函数。
3.可以把构造函数定义为private /protected ,这样就不能在外部实例化该类,这样不相关的类就不能访问她了。
静态构造函数:类有一些静态的字段或属性,需要在第一次使用类之前,在外部源中初始化这些静态字段和属性。
1.静态构造函数没有访问限制符,其它c#代码不会调用它,它只是在第一次调用类的任何成员之前会执行它。
2.静态构造函数不能有任何参数,一个类只能定义一个静态构造函数。
11.扩展方法
1.一个类没有的源代码,需要给类添加方法。
2.扩展方法是个静态方法,需定义在静态类中。第一个参数是要扩展的类型,用this关键字修饰。
12 . 接口继承和实现继承:只继承接口的函数签名,后者还继承方法实现。
虚方法:(virtual)可以在如何派生类中重写该方法。
13.派生类的构造函数
14.泛型类型
默认值:由于不能把null 赋值给泛型类型,在给泛型类型赋默认值是用default 如: T doc=default(T);
15:委托
委托是实现对方法的引用,可以把方法当参数,进行传递。主要应用场景是实现对同步方法的异步调用(invoke,beginInvoke,endInvoke),也实现对控件的异步或并发访问。它是通过使用线程池中的线程来进行异步调用。
2.多播委托包含一个逐个调用的委托集合,如果通过委托调用的其中一个方法出现异常,整个迭代就会终止。为解决这个问题,委托添加了GetInvocationList()方法,用来遍历委托对象列表。
3.匿名方法:不用单独定义仅有委托引用的方法;匿名方法中不能包含跳转语句(break, goto,continue)跳转到匿名方法的外部,反之,匿名方法外部的跳转语句不能跳转到匿名方法内部;不能访问在匿名方法外部使用的ref和out参数。
4.lambda表达式。c#3.0用来替代匿名方法,给委托赋予实现代码。lambda运算符=> ,左边为参数列表,右侧为实现代码;
5.闭包:通过lambda表达是可以访问表达式块外部的变量;