零散知识点

1.值类型和引用类型的区别

      1. 值类型的变量赋值时是将真实数据的副本付给变量,而引用类型则是将对象的引用付给变量, 这会产生多个多个变量同时指向一个对象实例
      2. 值类型定义时,会在堆栈上分配内存,引用类型会在堆上分配内存
      3. 所有的值类型都有共同的基类:System.ValueType.所有值类型都已经实现了类容的比较equals() 方法,而引用类型在没有重写Equals()方法的情况下,任然采用引用比较。

2. 堆和栈的区别

    1. 栈由操作系统自动分配和释放,一般用于存放函数的参数和局部变量的值。堆有程序员分配和释放,如果程序不主动释放,可在GC进行回收,或在程序结束后由操作系统回收。
    2. 栈使用的是一级缓存,在调用时被分配空间,调用完毕立即释放;

堆使用的是二级缓存,生命周期由垃圾回收算法来决定。

3.结构和类的区别

  1. 结构是值类型,类是引用类型 。
  2. 结构里的成员都是public,类有其他的访问限定符
  3. 类是显示实物的一种抽象,结构包含不同类别数据的一种包装。所有类型只包含一些数据时,用结构比较合适。
  4. 结构不能继承,类可以。
  5. Sealed修饰类有什么特点

Sealed修饰类,表示该类为密封类。不能从它派生出其它类。所有sealed和abstract不能同时限定类

         6.结构不能定义不带参数的构造函数,类可以。因为运行库会提供隐式构造方法,把值类型初始成0,把引用类型初始成null.即使提供了带参数的构造函数,也不能绕过默认构造函数;

         7.结构不能直接给字段附默认值;

4.  类的访问限定符

        Partial: 类分成两个文件,分别在不同的文件中

       Public : 该类的访问不受限制。

       Internal:同一个assembly的文件间的才可引用,常见的用途是基于组件的开发。

成员的访问限定符

  Public:访问不受限制

  Private:只能在本类中访问

  Protected:在本类或其子类中可以访问

  Internal:同一程序集中

6、面向对象的3个基本特征

  1. 封装:把客观的事物封装成抽象的类,类可以吧自己的数据和方法公开给可信的类或对象进行使用,对不可信的进行信息隐藏;
  2. 继承:
  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;
}
}
View Code

 

8. 抽象类和接口

相同点: 

       1.都不能被实例化;

       2.都包含的未实现的方法;

      3. 派生类必须要实现未实现的方法,接口是所有定义的方法,抽象类是未定义的方法;

       4.他们都是实现扩展的一个手段。

不同点:

      1.抽象类是对类的不可变行为的抽象,这些修为可以在抽象类中定义和实现。接口是定义的一组行为规范,不能有实现和私有字段。

       2.一个类可以实现多个接口,但只能扩展一个父类。

      3.接口不具备继承的任何特点,只承诺能被调用的方法。

       4.如果抽象类实现接口,可以将接口的方法映射到抽象方法而不必实现,让子类去实现。 

   抽象类和接口的使用: 

     1.尽量避免使用继承来实现组建功能,而是用黑箱复用,即对象组合(把另一个类的对象组合到类中来实现功能组合);

    2.接口污染:接口应具备专一功能性,而不是多功能的;

    3.oop原则:把可变的和不可变的分离;抽象类和接口都是定义不可变的。

     4.如果创建的功能是在大范围的全异对象间使用,则使用接口;

    5.如果要设计大的功能单元,则用抽象类,如果在所有实现间提供通用的功能实现,则用接口。

    6.抽象类主要用于关系密切的对象; 接口用于为不相关的类提供通用功能;

9.类的设计原则

  1. 开闭原则:在扩展方面开放,在修改方面封闭。多用接口、抽象类、多态等技术来设计。

         实现方法:把不变的部分抽象成接口;

         接口要注意最小功能实现;

         模块之间的调用要通过接口进行,这样即使实现层发生变化,也无需修改调用层的代码;   

 

  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表达是可以访问表达式块外部的变量;

 

 

 

 

 

 

 

 

 
posted @ 2017-11-16 10:47  xubenhua  阅读(312)  评论(0编辑  收藏  举报