zoukankan      html  css  js  c++  java
  • C#基础

    最近感觉自己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的用法了,这两个的用法主要都是为了方便我们少写一些代码。

  • 相关阅读:
    swift函数
    Swift数据类型
    swift的特点
    图片适配、九宫切图
    iOS中视图控制器的生命周期
    CocoaPods的安装与使用
    SQLite3的使用
    Pickers应用程序
    多视图应用
    OC对象的三大特性:封装、继承和 多态
  • 原文地址:https://www.cnblogs.com/zfylzl/p/9829407.html
Copyright © 2011-2022 走看看