zoukankan      html  css  js  c++  java
  • 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#的两种数据类型:值类型和引用类型
     
     
     
     
     
  • 相关阅读:
    6、redux源码解析
    5、redux源码解析
    4、redux源码解析
    3、redux码源
    2、redux源码探索
    1、redux源码探索
    Second Autoprefixer control comment was ignored. Autoprefixer applies control comment to whole block, not to next rules.
    Linux命令——whereis
    Linux命令——which
    Linux命令——tail
  • 原文地址:https://www.cnblogs.com/jaysen/p/3036515.html
Copyright © 2011-2022 走看看