C#深入浅出 语法中各种比较(三)

1.类,结构

相似之处:类与结构的定义相似
 
结构示例 
public struct Person
{  
    string Name;  
    int height;  
    int weight;
    public bool overWeight() 
    {
         //implement something
    } 
} 

 

 类示例
public class TestTime  
{  
    int hours;
    int minutes;  
    int seconds;  
    public void passtime()
    {  
        //implementation of behavior  
    }
} 

 

 调用过程
public class Test
{
     public static ovid Main  ()
   {
       Person Myperson=new Person //声明结构 
     TestTime Mytime=New TestTime //声明类
   }
} 

从上面的例子中我们可以看到类的声明和结构的声明非常类似

类和结构的区别:
  结构是值类型:值类型在堆栈上分配地址,所有的基类型都是结构类型。例如:int 对应System.int32 结构string 对应 system.string 结构 ,通过使用结构可以创建更多的值类型。
  类是引用类型:引用类型在堆上分配地址 ,堆栈的执行效率要比堆的执行效率高。可是堆栈的资源有限,不适合处理大的逻辑复杂的对象。所以结构处理作为基类型对待的小对象,而类处理某个商业逻辑  因为结构是值类型所以结构之间的赋值可以创建新的结构而类是引用类型。类之间的赋值只是复制引用 
注:  1.虽然结构与类的类型不一样,可是他们的基类型都是对象“object”,c#中所有类型的基类型都是object
        2.虽然结构的初始化也使用了New 操作符可是结构对象依然分配在堆栈上而不是堆上,如果不使用“新建”(new),那么在初始化所有字段之前,字段将保持未赋值状态,且对象不可用  
        3.继承性 :
      结构:不能从另外一个结构或者类继承,本身也不能被继承,虽然结构没有明确的用sealed声明,可是结构是隐式的sealed . 
      :完全可扩展的,除非显示的声明sealed 否则类可以继承其他类和接口,自身也能被继承  [NextPage] 
 
        注:虽然结构不能被继承 ,可是结构能够继承接口,方法和类继承接口一样  例如:结构实现接 
 
interface IImage
{
    void Paint();
}
struct Picture : IImage
{
  public void Paint()
   { 
    // painting code goes here
   }
   private int x, y, z; // other struct members
}
        4.内部结构:
                 结构,  没有默认的构造函数,但是可以添加构造函数,  没有析构函数 , 没有 abstract 和 sealed(因为不能继承) , 不能有protected 修饰符  ,可以不使用new 初始化 , 在结构中初始化实例字段是错误的 。
                  ,   有默认的构造函数 , 有析构函数  ,可以使用 abstract 和 sealed  有protected 修饰符 , 必须使用new 初始化 。 
 
        5.如何选择结构还是类 : 讨论了结构与类的相同之处和差别之后,下面讨论如何选择使用结构还是类。 1.堆栈的空间有限,对于大量的逻辑的对象,创建类要比创建结构好一些  2.结构表示如点、矩形和颜色这样的轻量对象。例如:如果声明一个含有1000 个点对象的数组,则将为引用每个对象分配附加的内存。在此情况下,结构的成本较低。  3.在表现抽象和多级别的对象层次时,类是最好的选择 4.大多数情况下该类型只是一些数据时结构时最佳的选择   

 
2.抽象类与接口
  抽象类主要用于关系密切的对象,利于代码统一规范;接口主要针对不相关的类,实现 某一功能
  抽象类在定义类型方法的时候,可以给出方法的实现部分,也可以不给出,但是抽象方法必须定义在抽象类中;而对于接口来说,其中所定义的方法都不能给出实现部分 
public abstract class AbsTest 
{ 
  public virtual void Test() 
  { 
    Debug.WriteLine("Test"); 
  } 
  public abstract void NewTest();
} 
public interface ITest 
{ 
  void Test(); 
  void NewTest();
}

 

  继承类对于两者所涉及方法的实现是不同的。继承类对于抽象类所定义的非抽象方法,可以不用重写,也就是说,可以延用抽象类的方法,对于抽象类中的抽象方法(隐式为虚方法),必须被覆盖,即若某个类继承了一个抽象类,则该类一定要实现基类中的抽象方法,不能不实现或者有选择的实现;而对于接口类所定义的方法或者属性来说,在继承类中必须要给出相应的方法和属性实现。在抽象类中,新增一个方法的话,继承类中可以不用作任何处理;而对于接口来说,则需要修改继承类,提供新定义的方法。

接口相对于抽象类的优势:

  好处一,接口不光可以作用于引用类型,也可以作用于值类型。而抽象类来说,只能作用于引用类型。

  好处二,.Net的类型继承只能是单继承的,也就是说一个类型只能继承一个类型,而可以继承多个接口。其实,我对于这一点也比较赞同,多继承会使继承树变的混乱。

  好处三,由于接口只是定义属性和方法,而与真正实现的类型没有太大的关系,因此接口可以被多个类型重用。相对于此,抽象类与继承类的关系更紧密些。

  好处四,通过接口,可以减少类型暴露的属性和方法,从而便于保护类型对象。当一个实现接口的类型,可能包含其他方法或者属性,但是方法返回的时候,可以返回接口对象,这样调用端,只能通过接口提供的方法或者属性,访问对象的相关元素,这样可以有效保护对象的其他元素。

好处五,减少值类型的拆箱操作。对于Struct定义的值类型数据,当存放集合当中,每当取出来,都需要进行拆箱操作,这时采用Struct+Interface结合的方法,从而降低拆箱操作。

  相对于抽象类来说,接口有这么多好处,但是接口有一个致命的弱点,就是接口所定义的方法和属性只能相对于继承它的类型(除非在继承类中修改接口定义的函数标示),那么对于多层继承关系的时候,光用接口就很难实现。因为如果让每个类型都去继承接口而进行实现的话,首先不说编写代码比较繁琐,有时候执行的结果还是错误,尤其当子类型对象隐式转换成基类对象进行访问的时候。

  那么这时候,需要用接口结合虚方法来实现。其实在继承中,到底使用接口还是抽象类。接口是固定的,约定俗成的,因此在继承类中必须提供接口相应的方法和属性的实现。而对于抽象类来说,抽象类的定义方法的实现,贯穿整个继承树,因此其中方法的实现或者重写都是不确定的。因此相对而言,抽象类比接口更灵活一些。

如下给出两者的简单对比表格:


 

接口

抽象类

多继承

支持

不支持

类型限制

没有

有,只能是引用类型

方法实现

继承类型中必须给出方法实现

继承类中可以不给出

扩展性

比较麻烦

相对比较灵活

多层继承

比较麻烦,需要借助虚函数

比较灵活

 


 
3.值类型和引用类型
区别主要是在内存中存储的方式不一样,值类型存储在栈上,而引用类型是先在内存上开辟一个空间保存该类型信息称为堆,而引用类型指向一个栈空间,该空间保存了存储该引用类型堆的地址。值类型只需要一次寻址,所以效率高。主要有数值类型,结构,枚举,bool;引用类型主要有接口、类、数组、字符串,委托。引用类型的赋值是只是复制了对对象的引用,而值类型是复制对象本身,将复制包含的值,比如将一个引用类型赋给另外一个引用类型,他们就都指向一个地址;而如果将一个值类型赋给另外一个值类型将改变该值类型的值。
值传递:将数值复制一份传递,数值本身不做修改;
引用传递:将数值所处的地址传递过去,实参和形参共用一个内存空间
 
下图为C#的两种数据类型:值类型和引用类型
 
 
 
 
 
posted @ 2013-05-12 15:51  天空中一朵艳阳  阅读(345)  评论(0编辑  收藏  举报