[你必须知道的.NET] 第六回:深入浅出关键字---base和this

本文将介绍以下内容:

  • 面向对象基本概念
  • base关键字深入浅出
  • this关键字深入浅出

 

1. 引言

new关键字引起了大家的不少关注,尤其感谢Anders Liu的补充,让我感觉博客园赋予的交流平台真的无所不在。所以,我们就有必要继续这个话题,把我认为最值得关注的关键字开展下去,本文的重点是访问关键字(Access Keywords):base和this。虽然访问关键字不是很难理解的话题,我们还是有可以深入讨论的地方来理清思路。还是老办法,我的问题先列出来,您是否做好了准备。

  1. 是否可以在静态方法中使用base和this,为什么?
  2. base常用于哪些方面?this常用于哪些方面?
  3. 可以base访问基类的一切成员吗?
  4. 如果有三层或者更多继承,那么最下级派生类的base指向那一层呢?例如.NET体系中,如果以base访问,则应该是直接父类实例呢,还是最高层类实例呢?
  5. 以base和this应用于构造函数时,继承类对象实例化的执行顺序如何? 

2. 基本概念

base和this在C#中被归于访问关键字,顾名思义,就是用于实现继承机制的访问操作,来满足对对象成员的访问,从而为多态机制提供更加灵活的处理方式。 

2.1 base关键字

其用于在派生类中实现对基类公有或者受保护成员的访问,但是只局限在构造函数、实例方法和实例属性访问器中,MSDN中小结的具体功能包括:

  • 调用基类上已被其他方法重写的方法。
  • 指定创建派生类实例时应调用的基类构造函数。 

2.2 this关键字

其用于引用类的当前实例,也包括继承而来的方法,通常可以隐藏this,MSDN中的小结功能主要包括:

  • 限定被相似的名称隐藏的成员
  • 将对象作为参数传递到其他方法
  • 声明索引器 

3. 深入浅出

3.1 示例为上

下面以一个小示例来综合的说明,base和this在访问操作中的应用,从而对其有个概要了解,更详细的规则和深入我们接着阐述。本示例没有完全的设计概念,主要用来阐述base和this关键字的使用要点和难点阐述,具体的如下: 

base和this示例

3.2 示例说明

上面的示例基本包括了base和this使用的所有基本功能演示,具体的说明可以从注释中得到解释,下面的说明是对注释的进一步阐述和补充,来说明在应用方面的几个要点:

  1. base常用于,在派生类对象初始化时和基类进行通信。
  2. base可以访问基类的公有成员和受保护成员,私有成员是不可访问的。
  3. this指代类对象本身,用于访问本类的所有常量、字段、属性和方法成员,而且不管访问元素是任何访问级别。因为,this仅仅局限于对象内部,对象外部是无法看到的,这就是this的基本思想。另外,静态成员不是对象的一部分,因此不能在静态方法中引用this。
  4. 在多层继承中,base可以指向的父类的方法有两种情况:一是有重载存在的情况下,base将指向直接继承的父类成员的方法,例如Audi类中的ShowResult方法中,使用base访问的将是Car.ShowResult()方法,而不能访问Vehicle.ShowResult()方法;而是没有重载存在的情况下,base可以指向任何上级父类的公有或者受保护方法,例如Audi类中,可以使用base访问基类Vehicle.Run()方法。这些我们可以使用ILDasm.exe,从IL代码中得到答案。 
.method public hidebysig virtual instance void 
        ShowResult() cil managed
{
  
// 代码大小       27 (0x1b)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldarg.
0
  //base调用父类成员
  IL_0002:  call       instance void Anytao.net.My_Must_net.Car::ShowResult()
  IL_0007:  nop
  IL_0008:  ldarg.
0
  //base调用父类成员,因为没有实现Car.Run(),所以指向更高级父类
  IL_0009:  call       instance void Anytao.net.My_Must_net.Vehicle::Run()
  IL_000e:  nop
  IL_000f:  ldstr      
"It's audi's result."
  IL_0014:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0019:  nop
  IL_001a:  ret
// end of method Audi::ShowResult

3.3 深入剖析 

如果有三次或者更多继承,那么最下级派生类的base指向那一层呢?例如.NET体系中,如果以base访问,则应该是直接父类实例呢,还是最高层类实例呢?

首先我们有必要了解类创建过程中的实例化顺序,才能进一步了解base机制的详细执行过程。一般来说,实例化过程首先要先实例化其基类,并且依此类推,一直到实例化System.Object为止。因此,类实例化,总是从调用System.Object.Object()开始。因此示例中的类Audi的实例化过程大概可以小结为以下顺序执行,详细可以参考示例代码分析。

  1. 执行System.Object.Object();
  2. 执行Vehicle.Vehicle(string name, int speed);
  3. 执行Car.Car();
  4. 执行Car.Car(string name, int speed);
  5. 执行Audi.Audi();
  6. 执行Audi.Audi(string name, int speed)。

我们在充分了解其实例化顺序的基础上就可以顺利的把握base和this在作用于构造函数时的执行情况,并进一步了解其基本功能细节。

下面更重要的分析则是,以ILDASM.exe工具为基础来分析IL反编译代码,以便更深层次的了解执行在base和this背后的应用实质,只有这样我们才能说对技术有了基本的剖析。

Main方法的执行情况为:

IL分析base和this执行

 因此,对重写父类方法,最终指向了最高级父类的方法成员。

 4. 通用规则

  • 尽量少用或者不用base和this。除了决议子类的名称冲突和在一个构造函数中调用其他的构造函数之外,base和this的使用容易引起不必要的结果。
  • 在静态成员中使用base和this都是不允许的。原因是,base和this访问的都是类的实例,也就是对象,而静态成员只能由类来访问,不能由对象来访问。
  • base是为了实现多态而设计的。
  • 使用this或base关键字只能指定一个构造函数,也就是说不可同时将this和base作用在一个构造函数上。
  • 简单的来说,base用于在派生类中访问重写的基类成员;而this用于访问本类的成员,当然也包括继承而来公有和保护成员。
  • 除了base,访问基类成员的另外一种方式是:显示的类型转换来实现。只是该方法不能为静态方法。

5. 结论

base和this关键字,不是特别难于理解的内容,本文之所以将其作为系列的主题,除了对其应用规则做以小结之外,更重要的是在关注其执行细节的基础上,对语言背景建立更清晰的把握和分析,这些才是学习和技术应用的根本所在,也是.NET技术框架中本质诉求。对学习者来说,只有从本质上来把握概念,才能在变化非凡的应用中,一眼找到答案。 

言归正传,开篇的几个题目,不知读者是否有了各自的答案,我们不妨畅所欲言,做更深入的讨论,以便揭开其真实的面纱。 

 

参考文献

(USA)Stanley B.Lippman, C# Primer

(USA)David Chappell, Understanding .NET

(Cnblog)Bear-Study-HardC#学习笔记(二):构造函数的执行序列

广而告之

[预告]

另外鉴于前几个主题的讨论中,不管是类型、关键字等都涉及到引用类型和值类型的话题,我将于近期发表相关内容的探讨,主要包括3个方面的内容,这是本系列近期动向,给自己做个广告。祝各位愉快。 

[声明] 

本文的关键字指的是C#中的关键字概念,并非一般意义上的.NET CRL范畴,之所以将这个主题加入本系列,是基于在.NET体系下开发的我们,何言能逃得过基本语言的只是要点。所以大可不必追究什么是.NET,什么是C#的话题,希望大家理清概念,有的放肆。

温故知新

[开篇有益]

[第一回:恩怨情仇:is和as]

[第二回:对抽象编程:接口和抽象类]

[第三回:历史纠葛:特性和属性]

[第四回:后来居上:class和struct]

[第五回:深入浅出关键字---把new说透]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438757.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分治算法求最大最小值c语言,[蓝桥杯][算法提高VIP]和最大子序列 (C语言代码)分治法...

解题思路:注意事项:参考代码:#include #include #include #include #include #include using namespace std;const int maxn 100001;int a[maxn];int maxsum(int *A, int x, int y) //返回左闭右开区间[x,y)中的最大连续和{int v, L, R, maxs;if(y-x 1) return A[x];int m …

[你必须知道的.NET] 第七回:品味类型---从通用类型系统开始

本文将介绍以下内容: .NET 基础架构概念 类型基础通用类型系统CLI、CTS、CLS的关系简述1. 引言 本文不是连环画,之所以在开篇以图形的形式来展示本文主题,其实就是想更加特别的强调这几个概念的重要性和关注度,同时希望从剖析其关…

二叉排序树查找的c语言程序,C语言二叉排序(搜索)树实例

本文实例为大家分享了C语言二叉排序(搜索)树实例代码,供大家参考,具体内容如下/**1.实现了递归 非递归插入(创建)二叉排序(搜索)树;分别对应Insert_BinSNode(TBinSNode* T,int k),NonRecursion_Insert_BinSNode(TBinSNode* T,int k);2.实现了…

[你必须知道的.NET] 第八回:品味类型---值类型与引用类型(上)-内存有理

本文将介绍以下内容: 类型的基本概念 值类型深入引用类型深入值类型与引用类型的比较及应用1. 引言 买了新本本,忙了好几天系统,终于开始了对值类型和引用类型做个全面的讲述了,本系列开篇之时就是因为想写这个主题,…

linux init 7,Linux 之 init命令

一、init是Linux系统操作中不可缺少的程序之一。所谓的init进程,它是一个由内核启动的用户级进程。内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式&am…

[你必须知道的.NET]第九回:品味类型---值类型与引用类型(中)-规则无边

接上回[第八回:品味类型---值类型与引用类型(上)-内存有理]的探讨,继续我们关注值类型和引用类型的话题。 本文将介绍以下内容: 类型的基本概念 值类型深入引用类型深入值类型与引用类型的比较及应用1. 引…

md5字符串输入c语言,请问C语言怎么实现对一长串字符进行MD5加密?

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼typedef unsigned char *POINTER;typedef unsigned short int UINT2;typedef unsigned long int UINT4;#define S11 7#define S12 12#define S13 17#define S14 22#define S21 5#define S22 9#define S23 14#define S24 20#define …

[你必须知道的.NET]第十回:品味类型---值类型与引用类型(下)-应用征途

本文将介绍以下内容: 类型的基本概念 值类型深入引用类型深入值类型与引用类型的比较及应用 [下载]:[类型示例代码] 1. 引言 值类型与引用类型的话题经过了两个回合([第八回:品味类型---值类型与引用类型(上&#xf…

lfsr算法c语言,求助:如何用C语言实现LFSR加密

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼includevoidLFSR(unsigned char pzt[],unsigned char pjg[],int n){unsigned char t0;int c0,i;for(i0;it^(pzt[i]&pjg[i]);t^((t<<1)^(t<<2)^(t<<3)^(t<<4)^(t<<5)^(t<<6)^(t<<7))…

c语言提供了三种预处理命令,9、C语言之预处理命令

预处理命令基本概念&#xff1a;ANSI C标准规定可以在C源程序中加入一些“预处理命令”&#xff0c;以改进程序设计环境&#xff0c;提高编程效率。这些预处理命令是由ANSI C同一规定的&#xff0c;但是它们不是C语言本身的组成部分&#xff0c;不能直接对它们进行编译(因为编译…

[你必须知道的.NET]第十一回:参数之惑---传递的艺术(上)

本文将介绍以下内容&#xff1a; 按值传递与按引用传递深论ref和out比较 参数应用浅析 1. 引言 接上回《第九回&#xff1a;品味类型---值类型与引用类型&#xff08;中&#xff09;&#xff0d;规则无边》中&#xff0c;对值类型和引用类型的讨论&#xff0c;其中关于string…

[你必须知道的.NET]第十二回:参数之惑---传递的艺术(下)

本文将介绍以下内容&#xff1a; 按值传递与按引用传递深论ref和out比较 参数应用浅析 接上篇继续&#xff0c;『第十一回&#xff1a;参数之惑---传递的艺术&#xff08;上&#xff09;』 4.2 引用类型参数的按值传递 当传递的参数为引用类型时&#xff0c;传递和操作的是指…

android 自定义相机源码,Android 自定义相机及分析源码

Android 自定义相机及分析源码使用Android 系统相机的方法&#xff1a;要想让应用有相机的action&#xff0c;咱们就必须在清单文件中做一些声明&#xff0c;好让系统知道&#xff0c;如下action的作用就是声明action的类型&#xff0c;便于Intent的使用&#xff0c;category的…

[你必须知道的.NET]第十三回:从Hello, world开始认识IL

本文将介绍以下内容&#xff1a; IL代码分析方法 Hello, world历史 .NET学习方法论1. 引言 1988年Brian W. Kernighan和Dennis M. Ritchie合著了软件史上的经典巨著《The C programming Language》&#xff0c;我推荐所有的程序人都有机会重温这本历史上的经典之作。从那时起…

android服务器怎么做的,[Android]Android 制作一个HTTP服务器应用

上传文件开始想用apache的开源库获取文件&#xff0c;但是失败了&#xff0c;要么文件不全&#xff0c;要么就完全为空&#xff0c;还是自己写。文件上传请求头的部分内容contentType:multipart/form-data; boundary----WebKitFormBoundaryHpUAY0qCryu0Oc7o我们需要获取boundar…

[你必须知道的.NET]第十四回:认识IL代码---从开始到现在

本文将介绍以下内容&#xff1a; IL代码分析方法 IL命令解析 .NET学习方法论 1. 引言 自从『你必须知道.NET』系列开篇以来&#xff0c;受到大家很多的关注和支持&#xff0c;给予了anytao巨大的鼓励和动力。俱往昔&#xff0c;我发现很多的园友都把…

android 获取服务对象,android 如何取得正在运行的service对象

在写有关推送的代码&#xff0c;用的长连接的方式。具体逻辑&#xff1a;登录时 启service&#xff0c;service中启一个线程&#xff0c;线程中构建一个CommunicateManegr对象&#xff0c;此对象里面有一个BlockingDeque双端队列处理包的顺序问题&#xff0c; 还有若干线程分别…

[你必须知道的.NET]第十五回:继承本质论

本文将介绍以下内容&#xff1a; 什么是继承&#xff1f;继承的实现本质1. 引言 关于继承&#xff0c;你是否驾熟就轻&#xff0c;关于继承&#xff0c;你是否了如指掌。 本文不讨论继承的基本概念&#xff0c;我们回归本质&#xff0c;从编译器运行的角度来揭示.NET继承中的…

海岸鸿蒙2018年标准物质,海岸鸿蒙——20年权威的标准物质研制单位

摘要&#xff1a;海岸鸿蒙创办于1996年&#xff0c;是专业从事国家标准物质研发、生产、销售的高新技术企业。海岸鸿蒙创办于1996年&#xff0c;是专业从事国家标准物质研发、生产、销售的高新技术企业。海岸鸿蒙自创办以来&#xff0c;一直秉持“以市场为导向&#xff0c;以科…

[你必须知道的.NET]第十六回:深入浅出关键字---using全接触

本文将介绍以下内容&#xff1a; using指令的多种用法using语句在Dispose模式中的应用1. 引言 在.NET大家庭中&#xff0c;有不少的关键字承担了多种角色&#xff0c;例如new关键字就身兼数职&#xff0c;除了能够创建对象&#xff0c;在继承体系中隐藏基类成员&#xff0c;还在…