【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的实例已经没有被任何变量引用了,那么此时就会等待被垃圾回收器回收。

时间: 2025-01-16 04:50:00

【C#进阶系列】04 类型基础的相关文章

JavaScript进阶系列04,函数参数个数不确定情况下的解决方案

本篇主要体验函数参数个数不确定情况下的一个解决方案.先来看一段使用函数作为参数进行计算的实例. var calculate = function(x, y, fn) { return fn(x, y); }; var sum = function(x, y) { return x + y; }; var diff = function(x, y) { return x - y; }; var sumResult = calculate(1, 2, sum), diffResult = calcu

04.类型基础

所有类型都从System.Object派生 Object类型的公开方法 Equals.GetHashCode.GetType.ToString Object类型的受保护方法 MembervieseClone.Finalize new操作符所做的事情 1.它计算类型和它的所有基类中定义所有字段需要的字节数 2.它从托管堆中分配指定类型要求的字节数,从而分配对象的内存,分配的所有字节都设为零 3.初始化对象的成员 4.调用类型的构造函数 5.返回新建对象的引用 类型转换 CLR允许将一个对象转换成它

JavaScript进阶系列06,事件委托

在"JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数"中已经有了一个跨浏览器的事件处理机制.现在需要使用这个事件处理机制为页面元素注册事件方法. □ 点击页面任何部分触发事件 创建一个script1.js文件. (function() { eventUtility.addEvent(document, "click", function(evt) { alert('hello'); }); }(

JavaScript进阶系列07,鼠标事件

鼠标事件有Keydown, Keyup, Keypress,但Keypress与Keydown和Keyup不同,如果按ctrl, shift, caps lock......等修饰键,不会触发Keypress事件,而会触发Keydown和Keyup事件,这就是Keypress事件与Keydown.Keyup事件的不同之处.另外,通常使用Keypress事件来获取用户输入信息. 继续使用"JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件

JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数

本篇体验JavaScript事件的基本面,包括: ■ 事件必须在页面元素加载之后起效■ 点击事件的一个简单例子■ 为元素注册多个点击事件■ 获取事件参数 □ 事件必须在页面元素加载之后起效 有这样一段简单的代码: <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <style>

[转]C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解

本文转自:http://www.cnblogs.com/landeanfen/p/5501487.html 阅读目录 一.void无返回值 二.IHttpActionResult 1.Json(T content) 2.Ok(). Ok(T content) 3.NotFound() 4.其他 5.自定义IHttpActionResult接口的实现 三.HttpResponseMessage 四.自定义类型 五.总结 正文 前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学

C#进阶系列——WebApi 身份认证解决方案:Basic基础认证

前言:最近,讨论到数据库安全的问题,于是就引出了WebApi服务没有加任何验证的问题.也就是说,任何人只要知道了接口的url,都能够模拟http请求去访问我们的服务接口,从而去增删改查数据库,这后果想想都恐怖.经过一番折腾,总算是加上了接口的身份认证,在此记录下,也给需要做身份认证的园友们提供参考. WebApi系列文章 C#进阶系列--WebApi接口测试工具:WebApiTestClient C#进阶系列--WebApi 跨域问题解决方案:CORS C#进阶系列--WebApi身份认证解决方

C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(二)

前言:上篇介绍了下封装BootstrapHelper的一些基础知识,这篇继续来完善下.参考HtmlHelper的方式,这篇博主先来封装下一些常用的表单组件.关于BootstrapHelper封装的意义何在,上篇评论里面已经讨论得太多,这里也不想过多纠结.总之一句话:凡事有得必有失,就看你怎么去取舍.有兴趣的可以看看,没兴趣的权当博主讲了个“笑话”吧. 本文原创地址:http://www.cnblogs.com/landeanfen/p/5746166.html BootstrapHelper系列

C#进阶系列——WebApi 接口测试工具:WebApiTestClient

C#进阶系列--WebApi 接口测试工具:WebApiTestClient 前言:这两天在整WebApi的服务,由于调用方是Android客户端,Android开发人员也不懂C#语法,API里面的接口也不能直接给他们看,没办法,只有整个详细一点的文档呗.由于接口个数有点多,每个接口都要详细说明接口作用.参数类型.返回值类型等等,写着写着把博主惹毛了,难道这种文档非要自己写不成?难道网上没有这种文档的展示工具吗?带着这两个问题,在网络世界里寻找,网络世界很奇妙,只要你用心,总能找到或多或少的帮助