C#基础 - this和base的用法

最近感觉自己C#基础不够扎实,所以又回去看了一些C#的基础知识,这里主要讲解一下比较用的到的this和base的用法。

this是对象级别的使用,指向的是当前实例化的对象,主要有三种用法:

第一种,在实例化构造函数的时候,为了避免传入的参数跟类的字段同名,使用this来区分开,避免混乱。

class MyClass
{
    private int age;
    private string name;
    public MyClass(int age, string name)
    {
        this.age = age;
        this.name = name;
    }
}

这里this.age的age是MyClass的字段age。

第二种,在构造函数链里面使用,在类的一个构造函数中,通过this指向一个主构造函数。

这种用法主要是为了避免实例化构造函数需要传入太多参数值。在调用的过程中,先去调用主构造函数,完了以后再调用自己的构造函数。

class MyClass
{
    private int age;
    private string name;
    private bool sex;
    private string address;
    public MyClass(int age, string name)
    {
        this.age = age;
        this.name = name;
    }

    public MyClass(int age, bool sex) 
      : this("", sex, "") { this.age = age; } //这里写一个主构造函数 public MyClass(string name, bool sex, string address) { this.name = name; this.sex = sex; this.address = address; } }

第二个构造函数,传入了age和sex两个参数,在执行的时候会先调用下面的主构造函数,给name,sex和address赋值,完了再回来执行当前的构造函数,给age赋值

第三种是用在扩展方法中,在第一个参数前面加上this,表示对改类型的一个扩展

public static List<ShipMethod> GetSupportedShipMethods(this PlatformType platformType)
        {
            List<ShipMethod> methods = null;
            var log = new LogisticsServiceNameAttribute();
            switch (platformType)
            {
                case PlatformType.速卖通:
                    methods = Enum.GetValues(typeof(Somitech.Entity.ShipMethod)).Cast<ShipMethod>()
                        .Where(s => s.HasAttribute(typeof(LogisticsServiceNameAttribute)) && !s.HasAttribute(typeof(ObsoleteAttribute)) && s.GetLogisticsServiceName().AliExpress != null).ToList();
                    break;
                case PlatformType.敦煌:
                    methods = Enum.GetValues(typeof(Somitech.Entity.ShipMethod)).Cast<ShipMethod>()
                        .Where(s => s.HasAttribute(typeof(LogisticsServiceNameAttribute)) && !s.HasAttribute(typeof(ObsoleteAttribute)) && s.GetLogisticsServiceName().DhGate != null).ToList();
                    break;
                default:
                    throw new NotImplementedException(platformType.ToString());
            }
            methods = methods.ToList();
            return methods;
        }

  

 

base是类级别的,指向基类,比较常用的用法也有两种:

第一种,在派生类的构造函数中调用基类的构造函数。

我们知道在派生类的实例化过程中,会先去调用基类的构造函数,正常是调用默认构造函数,这里我们可以指定调用哪个构造函数。

执行顺序是,先执行基类的带参数的构造函数,然后再执行派生类的构造函数。

public class MyBaseClass
{
    public MyBaseClass()
    {
        Console.WriteLine("基类无参构造函数!");
    }

    public MyBaseClass(int num)
    {
        Console.WriteLine("基类带有整型参数的构造函数!");
    }
}

public class MyClass : MyBaseClass
{
    public int age;

    public MyClass()
    {
    
    }
    
    //派生类调用基类带参数的构造函数,这里会调用MyBaseClass(int num)这个方法
    public MyClass(int num)
        : base(num)
    {
        age = 102;
        Console.WriteLine("派生类带有整型参数的构造函数!age=" + age);
    }
}

在MyClass类的构造函数MyClass(int num)被调用的时候,会先去调用基类中的构造函数MyBaseClass(int num)

第二种,在派生类的方法中调用已经被重写的基类的方法。

public class MyBaseClass
{
    public MyBaseClass()
    {
        Console.WriteLine("基类无参构造函数!");
    }

    public MyBaseClass(int num)
    {
        Console.WriteLine("基类带有整型参数的构造函数!");
    }
    
    public virtual void GetMyAge()
    {
        Console.WriteLine("我是基类,我的年龄最大!");
    }
}

public class MyClass : MyBaseClass
{
    public int age;

    //派生类调用基类带参数的构造函数,这里会调用MyBaseClass(int num)这个方法
    public MyClass(int num)
        : base(num)
    {
        age = 102;
        Console.WriteLine("派生类带有整型参数的构造函数!age=" + age);
    }
    
    public override void GetMyAge()
    {
    
base.GetMyAge(); Console.WriteLine("我是派生类,我的年龄比较小!"); } }

这里,我们再子类的GetMyAge方法中通过base.GetMyAge()来调用基类的被重写的方法,执行完基类方法以后,再执行方法剩下的部分。

会输出:

我是基类,我的年龄最大!   

我是派生类,我的年龄比较小!

 

最后,我们再通过一个控制台项目来结合this和base的用法使用一下,在控制台输入以下代码:

新建一个MyBaseClass的基类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatterns.Basic
{
    public class MyBaseClass
    {
        public MyBaseClass()
        {
            Console.WriteLine("基类无参构造函数!");
        }

        public MyBaseClass(int num)
        {
            Console.WriteLine("基类带有整型参数的构造函数!");
        }

        public virtual void GetMyAge()
        {
            Console.WriteLine("我是基类,我的年龄最大!");
        }
    }
}

再新建一个子类MyClass:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatterns.Basic
{
    public class MyClass : MyBaseClass
    {
        public int age;
        public static int age2;
        public static readonly object obj = new object();

        static MyClass()
        {
            age2 = 100;
            Console.WriteLine("执行静态构造函数!age2=" + age2);
        }

        public MyClass()
            : this(5)
        {
            age = 101;
            Console.WriteLine("派生类无参构造函数!age=" + age);
        }

        public MyClass(int num)
            : base(num)
        {
            age = 102;
            Console.WriteLine("派生类带有整型参数的构造函数!age=" + age);
        }

        public MyClass(int num, int kit)
        {
            Console.WriteLine("派生类带有两个参数的构造函数");
        }

        public override void GetMyAge()
        {
            base.GetMyAge();
            Console.WriteLine("我是派生类,我的年龄比较小!");
        }
    }
}

最后在Program文件的Main函数中输入以下代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DesignPatterns.Basic;

namespace DesignPatterns
{
    class Program
    {
        static void Main(string[] args)
        {
            //执行顺序是:静态构造函数 =》 基类带有参数的构造函数 =》派生类带有参数的构造函数 =》派生类无参构造函数
            MyClass myClass = new MyClass();
            
            //执行顺序是:基类带有参数的构造函数 =》 派生类带有参数的构造函数
            MyClass myClass1 = new MyClass(10);

            Console.ReadKey();
        }
    }
}

在这里,我们在子类中添加了三个字段,一个普通字段age,两个静态字段age2和obj,这里先讲讲静态字段的用法。

静态字段跟静态方法一样是通过类来调用的,所有的对象共享这个静态字段,这个字段一旦被初始化以后就不能再次赋值了,我们可以在申明的时候就去初始化,比如obj。如果在申明的时候没有初始化,那只能通过静态构造函数去初始化,比如age2。

一个类中如果存在静态构造函数,那么静态构造函数会被优先调用,而且只会被执行一次,真实的执行过程是:每次执行实例化构造函数的时候,都会去判断静态构造函数是否有被执行,如果没有就执行优先执行静态构造函数,如果执行了,就不再去执行。

所以在执行下面这个代码的时候,其实走了4步:MyClass myClass = new MyClass();

首先调用静态构造函数,给静态变量age2赋值,然后调用派生类的构造函数public MyClass() : this(5),但是因为这个构造函数通过this指向了主构造函数,所以需要先去调用主构造函数public MyClass(int num) : base(num),而主构造函数又通过base去调用了基类的带参数的构造函数public MyBaseClass(int num),执行顺序是:静态构造函数 =》 基类带有参数的构造函数 =》派生类带有参数的构造函数 =》派生类无参构造函数

正确的输出:

在执行MyClass myClass1 = new MyClass(10);这个方法的时候就简单多了,因为静态构造函数上面已经执行了,所以这里就不再执行。

顺序:基类带有参数的构造函数 =》 派生类带有参数的构造函数

以上就是大概base和this的用法了,这两个的用法主要都是为了方便我们少写一些代码。

转载于:https://www.cnblogs.com/zfylzl/p/9829407.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值