c# base和this的区别(base、this、virtual、override、static详解)

今天的程序调试中出现了以下错误,引发了我对base关键字的用法的疑惑,总结一下。

1、base关键字

用法1:

base是为了实现子类的方法中实现父类原有的方法。

this关键字代表本类对象,base关键字代表父类对象。

    如:

base.property;//调用父类的属性
base.method();//调用父类的方法

以下实例演示了派生类中调用用基类的方法,注意virtual、override关键词的使用。

(1)virtual关键字用于修改方法、属性、索引器或事件声明,并使它们可以在派生类派生类中被重写。注意静态属性上使用virtual关键字时错误的。

(2)override关键词用于扩展或修改继承的方法、属性、索引器或事件的抽象实现或虚实现。


    public class Person  //父类
    {
        protected string ssn = "444-55-6666";
        protected string name = "John L. Malgraine";

        public virtual void GetInfo()
        {
            Console.WriteLine("Name: {0}", name);
            Console.WriteLine("SSN: {0}", ssn);
        }
    }
    class Employee : Person   //派生类
    {
        public string id = "ABC567EFG";
        public override void GetInfo()
        {
            // Calling the base class GetInfo method:
            base.GetInfo();
            Console.WriteLine("Employee ID: {0}", id);
        }
    }

    class TestClass
    {
        static void Main()
        {
            Employee E = new Employee();
            E.GetInfo();
        }
    }
    /*
    Output
    Name: John L. Malgraine
    SSN: 444-55-6666
    Employee ID: ABC567EFG
    */

注意:访问父类(基类)成员只能在构造函数、实例方法或实例属性中进行,因此,从静态方法中使用base关键是错误的。我以上错误的原因就是因为静态方法中使用了base。

用法2:base关键字还可以指定创建派生类实例时应调用的基类的构造函数

public class BaseClass   //父类
{
    int num;

    public BaseClass()  //构造函数
    {
        Console.WriteLine("in BaseClass()");
    }

    public BaseClass(int i)  //构造函数
    {
        num = i;
        Console.WriteLine("in BaseClass(int i)");
    }

    public int GetNum()
    {
        return num;
    }
}

public class DerivedClass : BaseClass  //派生类
{
    // This constructor will call BaseClass.BaseClass()
    public DerivedClass() : base()   //派生类的构造函数调用基类的构造函数
    {
    }

    // This constructor will call BaseClass.BaseClass(int i)
    public DerivedClass(int i) : base(i)  //派生类的构造函数调用基类的构造函数
    {
    }

    static void Main()
    {
        DerivedClass md = new DerivedClass();   
        DerivedClass md1 = new DerivedClass(1);
    }
}
/*
Output:
in BaseClass()
in BaseClass(int i)
*/

2、this关键字

用法1:

  this代表当前类的实例对象

namespace Demo
{
    public class Test
    {
        private string scope = "全局变量";
        public string getResult()
        {
            string scope = "局部变量";
       // this代表Test的实例对象
       // 所以this.scope对应的是全局变量
        // scope对应的是getResult方法内的局部变量
            return this.scope + "-" + scope;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Test test = new Test();
                Console.WriteLine(test.getResult());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            finally
            {
                Console.ReadLine();
            }

        }
    }
}

 用法2:this串联构造函数

namespace Demo
{
    public class Test
    {
        public Test()
        {
            Console.WriteLine("无参构造函数");
        }
        // this()对应无参构造方法Test()
     // 先执行Test(),后执行Test(string text)
        public Test(string text) : this()
        {
            Console.WriteLine(text);
            Console.WriteLine("有参构造函数");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Test test = new Test("张三");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            finally
            {
                Console.ReadLine();
            }
        }
    }
}

3、 static关键字

       使用 static 修饰符声明属于类型本身而不是属于特定对象的静态成员。static 修饰符可用于类、字段、方法、属性、运算符、事件和构造函数,但不能用于索引器、析构函数或类以外的类型。

静态方法与非静态方法

a、静态方法的调用
类.静态方法名([参数列表])

非静态方法的调用
类 对象 = new 类的构造函数([参数列表])
对象.非静态方法名([参数列表])

静态方法是属于类的,而非静态方法是属于对象的;

b、内存的初始化
静态成员是在第一次使用时进行初始化。非静态的成员是在创建对象的时候。
静态构造函数只能被执行一次;非静态的构造函数可以根据需要进行多次使用。

c、内存中存储
静态的只有一块全局内存空间,非静态的可以有多块内存空间(副本)

d、释放
静态的一旦创建则在全局区一直存放,直到应用程序结束。非静态的则是由new关键字在堆中创建的。可以有多个副本。由GC进行释放。

注意:

(1)static变量及方法不用实例化对象就可以用类名.静态变量和类名.静态方法这种方式进行访问,这使得访问更加方便,不用手工实例化对象。对于某些只读变量和方法来说很适合共享。

(2)static与非static最大的区别就是static类型的变量及方法在调用的时候就在内存中分配了地址,且这个地址只有一份,故static可以直接访问。而非static必需手工去实例化该类,以对象的方式去访问变量和方法。

(3)在一个静态方法里去访问该类的非静态变量或方法,由于static是属于类本身的,是在类被调用的时候,static类型就已经生成,而非static此时并没有生成,它不属于这个类本身,它是属于这个类的对象。故在没有实例化成对象的时候,在静态方法中访问非静态是根本找不到它们的,它不属于这个类。

(4)在非静态方法中去访问静态,由于类被调用时,静态变量和方法就已经生成,也就是说它们属于这个类。既然已经存在,故不管是在静态方法中,还是非静态方法中都可以访问到它们。

(5)this表明对象本身,而在静态方法中并没有对象概念存在,它只有类本身这个概念,它和对象是属于两种互拆的状态,即我中无你,你中无我的情况。也就是说你用对象名.静态变量或对象名.静态方法是不可访问的。

(6)每个类都必须有构造函数,否则此类无法实例化成对象。而我们有时定义的类可以不写它的构造函数,这是因为编译器会帮我们加上一个静态的空构造函数。这样才能实例化。也可以用静态构造函数去初始化静态变量。

猜你喜欢

转载自blog.csdn.net/kenjianqi1647/article/details/84037929