C# base和this

 • 是否可以在静态方法中使用base和this,为什么?

  • base常用于哪些方面?this常用于哪些方面?

  • 可以base访问基类的一切成员吗?

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

  • 以base和this应用于构造函数时,继承类对象实例化的执行顺序如何?

  2. 基本概念

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

  2.1 base关键字

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

  • 调用基类上已被其他方法重写的方法。

  • 指定创建派生类实例时应调用的基类构造函数。

  2.2 this关键字

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

  • 限定被相似的名称隐藏的成员

  • 将对象作为参数传递到其他方法

  • 声明索引器  

  3. 深入浅出

  3.1 示例为上

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


using System;
namespace Anytao.net.My_Must_net
{
public class Action
{
public static void ToRun(Vehicle vehicle)
{
Console.WriteLine("{0} is running.", vehicle.ToString());
}
}
public class Vehicle
{
private string name;
private int speed;
private string[] array = new string[10];

public Vehicle()
{
}
//限定被相似的名称隐藏的成员
public Vehicle(string name, int speed)
{
this.name = name;
this.speed = speed;
}
public virtual void ShowResult()
{
Console.WriteLine("The top speed of {0} is {1}.", name, speed);
}
public void Run()
{
//传递当前实例参数
Action.ToRun(this);
}
//声明索引器,必须为this,这样就可以像数组一样来索引对象
public string this[int param]
{
get{return array[param];}
set{array[param] = value;}
}
}
public class Car: Vehicle
{
//派生类和基类通信,以base实现,基类首先被调用
//指定创建派生类实例时应调用的基类构造函数
public Car()
: base("Car", 200)
{ }

public Car(string name, int speed)
: this()
{ }

public override void ShowResult()
{
//调用基类上已被其他方法重写的方法
base.ShowResult();
Console.WriteLine("It's a car's result.");
}
}
public class Audi : Car
{
public Audi()
: base("Audi", 300)
{ }

public Audi(string name, int speed)
: this()
{
}
public override void ShowResult()
{
//由三层继承可以看出,base只能继承其直接基类成员
base.ShowResult();
base.Run();
Console.WriteLine("It's audi's result.");
}
}
public class BaseThisTester
{
public static void Main(string[] args)
{
Audi audi = new Audi();
audi[1] = "A6";
audi[2] = "A8";
Console.WriteLine(audi[1]);
audi.Run();
audi.ShowResult();
}
}
}

 

  3.2 示例说明

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

  • base常用于,在派生类对象初始化时和基类进行通信。

  • base可以访问基类的公有成员和受保护成员,私有成员是不可访问的。

  • this指代类对象本身,用于访问本类的所有常量、字段、属性和方法成员,而且不管访问元素是任何访问级别。因为,this仅仅局限于对象内部,对象外部是无法看到的,这就是this的基本思想。另外,静态成员不是对象的一部分,因此不能在静态方法中引用this。

  • 在多层继承中,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的实例化过程大概可以小结为以下顺序执行,详细可以参考示例代码分析。

  • 执行System.Object.Object();

  • 执行Vehicle.Vehicle(string name, int speed);

  • 执行Car.Car();

  • 执行Car.Car(string name, int speed);

  • 执行Audi.Audi();

  • 执行Audi.Audi(string name, int speed)。

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

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

Main方法的执行情况为:


.method public hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 代码大小 61 (0x3d)
.maxstack 3
.locals init (class Anytao.net.My_Must_net.Audi V_0)
IL_0000: nop
//使用newobj指令创建新的对象,并调用构造函数初始化
IL_0001: newobj instance void Anytao.net.My_Must_net.Audi::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.1
IL_0009: ldstr "A6"
IL_000e: callvirt instance void Anytao.net.My_Must_net.Vehicle::set_Item(int32,
string)
IL_0013: nop
IL_0014: ldloc.0
IL_0015: ldc.i4.2
IL_0016: ldstr "A8"
IL_001b: callvirt instance void Anytao.net.My_Must_net.Vehicle::set_Item(int32,
string)
IL_0020: nop
IL_0021: ldloc.0
IL_0022: ldc.i4.1
IL_0023: callvirt instance string Anytao.net.My_Must_net.Vehicle::get_Item(int32)
IL_0028: call void [mscorlib]System.Console::WriteLine(string)
IL_002d: nop
IL_002e: ldloc.0
IL_002f: callvirt instance void Anytao.net.My_Must_net.Vehicle::Run()
IL_0034: nop
IL_0035: ldloc.0
//base.ShowResult最终调用的是最高级父类Vehicle的方法,
//而不是直接父类Car.ShowResult()方法,这是应该关注的
IL_0036: callvirt instance void Anytao.net.My_Must_net.Vehicle::ShowResult()
IL_003b: nop
IL_003c: ret
} // end of method BaseThisTester::Main

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

 

  4. 通用规则

  • 尽量少用或者不用base和this。除了决议子类的名称冲突和在一个构造函数中调用其他的构造函数之外,base和this的使用容易引起不必要的结果。

  • 在静态成员中使用base和this都是不允许的。原因是,base和this访问的都是类的实例,也就是对象,而静态成员只能由类来访问,不能由对象来访问。

  • base是为了实现多态而设计的。

  • 使用this或base关键字只能指定一个构造函数,也就是说不可同时将this和base作用在一个构造函数上。

  • 简单的来说,base用于在派生类中访问重写的基类成员;而this用于访问本类的成员,当然也包括继承而来公有和保护成员。

  • 除了base,访问基类成员的另外一种方式是:显示的类型转换来实现。只是该方法不能为静态方法。 

转载于:https://www.cnblogs.com/BrokenIce/p/6100076.html

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

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

相关文章

IE和Firefox对iframe document对象的差异性

在IE6、IE7中,我们可以使用 document.frames[ID].document 来访问iframe子窗口中的document对象,可是这是不符合W3C标准的写法,也是IE下独有的方法,在Firefox下却不可以使用,Firefox下使用的是符合W3C标准的 document.…

php利用ajax文件上传,如何在PHP中利用AjaxForm实现一个文件上传功能

如何在PHP中利用AjaxForm实现一个文件上传功能发布时间:2020-12-18 14:52:38来源:亿速云阅读:94作者:Leah如何在PHP中利用AjaxForm实现一个文件上传功能?针对这个问题,这篇文章详细介绍了相对应的分析和解答…

asp.net记录错误日志的方法

1、说明 在调试发布后的asp.net项目时有可能会遇到意想不到的错误,而未能及时的显示。这就需要记录日志来跟踪错误信息,所以写了个简单的记录信息的方法,记录简单的文本信息也可以使用。此方法是以生成文本文件的方式记录的,下面贴…

Flex DES加密

as3crypto:一个as3的关于加解密的开源项目 http://code.google.com/p/as3crypto/ 加密 var key:ByteArray new ByteArray(); key.writeUTFBytes("cf43qbhs"); var iv:ByteArray new ByteArray(); iv.writeUTFBytes("cf43qbhs"); va…

oracle建表代码,Oracle 建表(一对多)代码及相关约束示例

建表(一对多)代码及相关约束create table t_class(c_id number(3) primary key,c_name varchar2(20) not null);create table t_stu(s_id number(5) primary key,s_name varchar2(8) not null,sex char(2) default 男,birthday date,school_age number(2) check(school_age>…

Flex中的Base64加解密

Flex中的Base64加解密Flex sdk3就内置了Base64的加/解密工具类分别是mx.utils.Base64Encodermx.utils.Base64DecoderBase64Encoder用法如下: var str:String "原始字符串";//获取原始字符串var base64:Base64Encoder new Base64Encoder();base64.insert…

iOS10 UI教程管理层次结构

iOS10 UI教程管理层次结构 iOS10 UI教程管理层次结构,在一个应用程序中,如果存在多个层次结构,就需要对这些层次结构进行管理。在UIView类中提供了可以用来管理层次结构的方法,让开发者可以添加、移动、删除来自层次结构中的元素。…

flash影响中文输入

外部网页&#xff1a;鼠标离开flash时可以输入中文<s:Application mouseOut"IMEEnabled()"> /** * 允许中文输入法 */ protected function IMEEnabled():void { IME.enabledtrue; }内部控件&#xff1a;获取焦点时加IME.enabledtrue;

oracle rac添加用户组,oracle 11g rac 与 oracle 10 rac所需要建立的组和用户

oracle 11g rac配置1. Create OS groups using thecommand below. Enter these commands as the root user:#/usr/sbin/groupadd -g 501 oinstall#/usr/sbin/groupadd -g 502 dba#/usr/sbin/groupadd -g 504 asmadmin#/usr/sbin/groupadd -g 506 asmdba#/usr/sbin/groupadd -g …

appium()-The event firing

原文地址&#xff1a;https://github.com/appium/java-client/blob/master/docs/The-event_firing.md since 4.1.0 The purpose This feature allows end user to organize the event logging on the client side. Also this feature may be useful in a binding with standard…

Flash Builder非法关闭导致无法启动

"C:\Program Files\Adobe\Adobe Flash Builder 4.5\FlashBuilder.exe" -clean 有时候出于某种原因&#xff0c;Flash Builder被非法关闭了&#xff08;比如死机&#xff09;&#xff0c;这个时候再启动Flash Builder&#xff0c;就会提示错误&#xff0c;提示你去看一…

c# oracle datasource,C# 连接Oracle 数据库 示例源码下载

【实例简介】C# 实现 Oracle 数据库的 增删改查 操作【实例截图】【核心代码】using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using S…

前端学习(2169):vue-router安装和配置方式

main.js import VueRouter from vue-router import Vue from vue//安装插件 const routers new VueRouter({//配置之间的关系routes })export default router index.js import VueRouter from vue-router import Vue from vue//安装插件 const routers new VueRouter({//配…

(模板)网页游戏用的“内容区”的“图赏影音”模板

网页游戏&#xff0c;没图赏影音用到的 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml"> <head>…

wmode解决flash透明及层深问题

在做web开发中可能会遇到flash遮挡页面中元素的情况&#xff0c;无论怎么设置flash容器和层的深度(z-index)也无济于事&#xff0c;现有的解决方案是在插入flash的embed或object标签中加入”wmode”属性并设置为wmode“transparent”或”opaque”&#xff0c;但wmode属性到底是…

url oracle default schema,oracle @Table中使用schema时insert报错

第一部分测试情况如下:maven修改com.alibabadruid1.1.10实体类Table(name "dpcenter.xeuser")public class OUser {private String userid;private String username;...}测试代码public static void main(String[] args) {OracleStyle stylenew OracleStyle();Conne…