zoukankan      html  css  js  c++  java
  • 【C#进阶系列】04 类型基础

    关于System.Object

      所有类型都从System.Object派生而来。

      System.Object的公共方法中ToString()一般是返回对象的类型的全名,只有Int32这些类型将其重写后,新方法才会返回其值的字符串表示。

      其中还有两个受保护的方法:

        MemberwiseClone:深复制。

        Finalize:在垃圾回收器判断此对象应该被回收后,在对象的内存被实际回收前会调用此方法。

    关于类型判断和转换:

      用is来判断对象为某类型或者某类型的派生类,是为true,不是为false。

      用as转换对象A为另一类型,成功则返回对象A的引用,失败则返回null。

      以上两种方法都不同于用()进行强制转换,不会报异常。

      其实看代码更好懂一点:

    namespace MyTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                var Troty123 = new Man();
                Console.WriteLine(Troty123 is Man);//True
                Console.WriteLine(Troty123 is People);//True
                Console.WriteLine(Troty123 is Animal);//False
    
                object fuckBoy = new Man();
                Console.WriteLine((fuckBoy as Man).ToString());//MyTest.Man
                Console.WriteLine((fuckBoy as People).ToString());//MyTest.Man
                Console.WriteLine(((fuckBoy as Animal)==null).ToString());//True
                Console.Read();
            }
        }
        class People {}
        class Man:People{}
        class Animal {}
    }

    using指令为命名空间或类型创建别名

    using MySystemText = System.Text.StringBuilder;
    
    namespace MyTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                MySystemText myText = new MySystemText();
            }
        }
    }

    用于解决引用不同命名空间时,两个命名空间中有相同名称但功能不同的类型的问题。

    一个关于堆栈和类的故事

    先贴出示例代码

      class Program
        {
            static void Main(string[] args)
            {
                Show();
            }
            static void  Show() {
                People Troy123 = new People();
                Troy123.Die();
                Console.Read();
            }
        }
        class People{
            int age;
            public void Die() { }
        }

    我们就讲一下Show被调用后的故事:

    堆变化

    首先JIT编译器会吧Show的IL代码全部转换为本机CPU指令,这个时候就已经知道了本函数中会用到People这个类型。

    然后生成了一个System.Type类型的实例,我们这里叫People的类型对象A好了,里面有指向System.Type类型对象的指针,同步块索引,People的静态字段以及People的函数的入口。

    栈变化

    Show被调用后会先判断Show是否有参数传进来,有就压到栈中。(显然并没有

    然后Show在Main函数中的代码的地址会被压到栈中。

    然后类型Troy123 的引用地址被压入栈中。

    堆变化

    然后生成People类的实例,此实例包含People类的实例字段以及其基类的实例字段。

    且此实例的类型对象指针指向之前的A的地址。(多个People类的实例的类型对象指针都指向这一个地址

    然后调用Die(),

      如果Die函数是个虚函数,且实例是People的派生类Man的实例,且此派生类的Die函数override类People的Visual的Die函数。那么就应该实现类Man中的Die函数。(很显然不是

      如果不符合上面这种情况,那么就按照   调用Die函数的那个变量Troy123的类型   中的Die函数来实现,也就是说如果Troy123是People类型就实现People的Die,如果是派生类Man类型就实现Man的Die。(而显然上面的代码实现People的Die也就是说即使是People Troy123=new Man();实际上也是实现People的Die

    栈变化

    如果Show函数结束,那么CPU的指令指针会指向之前压到栈中的返回地址,然后退栈帧,然后此时栈帧反应Main函数的堆栈情况。

    堆变化

    而此时People的实例已经没有被任何变量引用了,那么此时就会等待被垃圾回收器回收。

  • 相关阅读:
    Oracle安装
    自动化测试开发
    Hyperf 接入阿里云ACM应用配置管理中心
    PHP redis有序集合实现分页
    虚拟现实与大数据
    树形数据结构化
    立即执行函数
    jQuery中的显示与隐藏
    jQuery中的HTML
    Django+Nginx配置+前后端交互
  • 原文地址:https://www.cnblogs.com/vvjiang/p/5237119.html
Copyright © 2011-2022 走看看