zoukankan      html  css  js  c++  java
  • 从C#的ValueType引发的思考

    无论上层语言类型多么复杂,在.NET平台上,都逃不过CTS的约束,今天,我想说的不是CTS,而是上层语言C#类型的一点研究。

    请看一下下面的这个代码段:

    1     public struct test
    2     {
    3         public override bool Equals(object obj)
    4         {
    5             return base.Equals(obj);
    6         }
    7     }

    这是我随便定义的一个结构,可以看到这个结构什么都没有继承,但是我却可以重写出Equals方法,这个方法来自哪里,这个结构的父亲又是谁呢?

    一、结构为什么不能继承类

    开门见山,ValueType!!

    是的,所有的结构都默认继承了该类,对的,是一个类,也就是说所有的结构都是有继承的,继承了ValueType,也是因为这样,所以结构不能再继承类了,只能继承接口,因为C#是单继承的。

    二、为什么每个结构都有ToString等方法

    ValueType!还是ValueType!

    因为结构默认继承了ValueType,也就是继承了Object,所以其实结构可以看成一个类,只是这个类很特别,比静态类,最终类还特别,区别包括:编译时会对他进行特殊处理,内存分配规则,不能被继承,实例化过程等等。所以结构在写法上和类很多地方很像,比如也可以拥有方法,等等,其实结构就是一个被阉割的非常厉害的类。

    三、enum的类型

    enum也是值类型,为什么这么说呢?

    1、typeof(枚举).BaseType可以看到enum的付类是System.Enum类,而System.Enum继承ValueType。

    2、enum的内存分配方式和值类型一样都是分配在栈上。

    3、enum是一种特殊的值类型,不能有结构,函数等等。

    但是System.Enum是类(引用类型),所以并不是所有继承ValueType的都是值类型(这个类我们自己也可以写个类去继承)

    四、哪些类型是值类型?值类型有什么特点?

    1、基础类型:decimal、bool、char、byte、sbyte、short、int、long、ushort、uint、ulong、single、double

    2、用户自定义值类型(以关键字struct声明的)

    3、enum特殊值类型

    值类型特点:值类型的数据特点很多,大多是和类做区分的,具体大家可以查一下资料哈。

    五、值类型可以继承接口,用接口访问值类型的时候,是值还是引用?

    大家猜一猜是值还是引用呢?好了先公布答案吧,答案是引用!

    IComparable i = 0; 当用接口指向值得时候,这个值会有一个装箱得过程,也就是值类型会装箱成一个引用类型。下面,我们用以下代码段来证明一下。

     1 //结构体班级   
     2 struct StructClass : IClass 
     3 {   
     4     public int Count;//人数   
     5     public void AddStudent()
     6     {   
     7         Count++;   
     8     }   
     9   
    10     public void ShowCount()
    11     {   
    12         Console.WriteLine(Count);   
    13     }   
    14   
    15 }   
    16 //接口   
    17 interface IClass
    18 {   
    19     void AddStudent();//添加学生   
    20     void ShowCount();//显示学生人数   
    21 }   
    22 class Program
    23 {   
    24     static void Main(string[] args) 
    25     {   
    26         StructClass s1 = new StructClass();   
    27         StructClass s2 = s1;   
    28         s1.AddStudent();   
    29         s1.ShowCount(); //输出1   
    30         s2.ShowCount(); //输出0   
    31         //说明s2和s1不指向同一个对象,s2=s1是创建了一个s1的副本   
    32         //这是值类型很显著的标志   
    33   
    34         IClass ic1 = new StructClass();   
    35         IClass ic2 = ic1;   
    36         ic1.AddStudent();   
    37         ic1.ShowCount();//输出1   
    38         ic2.ShowCount();//输出1   
    39         //说明s2和s1指向同一个对象,s2=s1是将s1的引用赋给s2   
    40         //这是引用类型很显著的标志   
    41     }   
    42 }  

    完毕!

  • 相关阅读:
    WINREG.H 编译出错
    WINREG.H 编译出错
    JS创建对象的几种方式
    清除radio单选框外边距
    Dragging MovieClips
    Cannot Say No
    分层提高软件系统的可测试性
    如何从技术上掌控项目?
    领导我只需要你告诉我你要做什么,怎么做让我来好吗?
    如何依据框架进行任务分解
  • 原文地址:https://www.cnblogs.com/xiaomowang/p/12395402.html
Copyright © 2011-2022 走看看