• 是否可以在静态方法中使用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,访问基类成员的另外一种方式是:显示的类型转换来实现。只是该方法不能为静态方法。

C# base和this的更多相关文章

  1. 小白解决CENTOS7错误:Cannot find a valid baseurl for repo: base/7/x86_6

    刚入手的MacBook想着学点东西,本汪还是决定玩玩CentOS服务器,安装好了VirtualBox + CentOS. 打开一看,懵逼了!命令行! 行吧,先装个图形界面: $sudo yum gro ...

  2. 分布式系列文章——从ACID到CAP/BASE

    事务 事务的定义: 事务(Transaction)是由一系列对系统中数据进行访问与更新的操作所组成的一个程序执行逻辑单元(Unit),狭义上的事务特指数据库事务. 事务的作用: 当多个应用程序并发访问 ...

  3. base的应用

    ------------父类   public class Person   {       public Person(string name,int age)    {       this.Na ...

  4. C# base 64图片编码解码

    使用WinForm实现了图片base64编码解码的 效果图: 示例base 64编码字符串: /9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKD ...

  5. c++ builder 2010 错误 F1004 Internal compiler error at 0x9740d99 with base 0x9

    今天遇到一个奇怪的问题,拷贝项目后,在修改,会出现F1004 Internal compiler error at 0x9740d99 with base 0x9 ,不管怎么改,删除改动,都没用,关闭 ...

  6. MVC中的BASE.ONACTIONEXECUTING(FILTERCONTEXT) 的作用

    一句话,就是调用base.OnActionExecuting(filterContext)这个后,才会执行后续的ActionFilter,如果你确定只有一个,或是不想执行后续的话,那么可以不用调用该语 ...

  7. 安装CentOS7文字界面版后,无法联网,用yum安装软件提示 cannot find a valid baseurl for repo:base/7/x86_64 的解决方法

    *无法联网的明显表现会有: 1.yum install出现 Error: cannot find a valid baseurl or repo:base 2.ping host会提示unknown ...

  8. 在ASP.NET Core中使用Angular2,以及与Angular2的Token base身份认证

    注:下载本文提到的完整代码示例请访问:How to authorization Angular 2 app with asp.net core web api 在ASP.NET Core中使用Angu ...

  9. 在ASP.NET Core中实现一个Token base的身份认证

    注:本文提到的代码示例下载地址> How to achieve a bearer token authentication and authorization in ASP.NET Core 在 ...

  10. SharePoint Claim base authentication EnsureUser 不带claim(i:0#.w|)user Failed

    环境信息: 带有Form base authentication(FBA).Active Directory Federation Services(ADFS).以及windows Authentic ...

随机推荐

  1. Linux_屏蔽360、scanv、QQ管家等IP扫描

    vi banip.sh #!/bin/bash echo "banip" iptables -A INPUT -s 221.204.203.0/24 -j DROP iptable ...

  2. C#页面添加提交数据后跳出小弹窗的功能

    很简单,将小弹窗部分写进一个div,利用div的visible属性去控制是否显示,首先默认为false; 当后台程序执行到插入数据完成后,设置session状态值为‘yes’ 判断,当session状 ...

  3. 关于iOS手势

    引: 前几天遇到一个坑,又仔细分析了一下事件的原理,不得不承认苹果的文档还是写的挺好的,网上就搜不到有几篇博客是介绍这个的,都是一些关于基本的用法的.这里纪录一下. 1.关于事件响应链. a.硬件接收 ...

  4. Solve error: Cannot open include file: 'X11/Xlocale.h': No such file or directory

    When you use FLTK with VS2010, you may get the error: fatal error C1083: Cannot open include file: ' ...

  5. WPF之拖动项滚动条自滚动(当拖动项到达高度的边界时候滚动条自己可以上下滚动)

    参考 http://www.cnblogs.com/ListenFly/p/3281997.html Point svPoint = e.GetPosition(sv); if (sv.ActualH ...

  6. [转]如何在 Visual Studio 中使用 Git 同步代码到 CodePlex

    本文转自:http://www.cnblogs.com/stg609/p/3673782.html 开源社区不管在国内还是国外都很火热,微软也曾因为没有开源而倍受指责,但是随着 .Net framew ...

  7. linux进程用户内存空间和内核空间

    When a process running in user mode requests additional memory, pages are allocated from the list of ...

  8. SecureCRT的相关问题

    1. 中文显示乱码的解决方法 2. 显示Linux中的颜色信息 3. 解决终端长时间无输入导致SSH连接中断的问题 4. 以公钥方式代替密码方式登录服务器 在SecureCRT中创建Public Ke ...

  9. Solr学习笔记之2、集成IK中文分词器

    Solr学习笔记之2.集成IK中文分词器 一.下载IK中文分词器 IK中文分词器 此文IK版本:IK Analyer 2012-FF hotfix 1 完整分发包 二.在Solr中集成IK中文分词器 ...

  10. MySql练习+加源代码

    一.设有一个数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher). 四个表的结构分别如表1-1的表(一)~表(四)所示,数据如表1 ...