C#基础知识之静态和非静态

项目中静态和非静态常被用到,什么时候需要用静态的,什么时候需要使用非静态,以及他们的区别是什么?

一、概述

  静态和非静态的不同地方,就是静态从程序一启动就会一直占用内存,而非静态只有在实例化的时候才会分配内存,每实例化一次对象都会重新分配一次内存。比如数据库连接类,因为经常使用到,所以使用Static,定义成静态类是最合适的。如果定义成非静态方法,每次调用的时候都会实例化,这样占用内存就会非常大。再比如登录后台的方法,只在登陆的时候调用一次登录方法,定义成非静态方法是比较合适的。总之就是经常被调用的就用静态的,反之使用非静态。现在好多公司的项目都会使用静态,内存换时间也是一种方式。毕竟目前增加内存的方式也有很多方式,而且成本也可以接受,只希望程序处理时间缩短,增加用户体验。

二、静态类

  静态类和非静态类的重要区别在于静态类不能实例化,也就是说静态类不能通过new创建静态类型的实例。在声明一个类时使用static关键词有两方面的含义:防止程序员实例化该静态类,防止在静态类里面定义所有的实例字段和方法。 

  非静态类可以包含静态的方法、字段、属性或事件。即使没有创建类的实例,也可以调用该类中的静态成员。   

  1、静态类的主要特征:

    (1)仅包括静态成员;

    (2)无法实例化;

    (3)静态类有抽象类和密封类的特点,无法被实例化和无法被继承;

    (4)不能包括实例构造函数;

  2、静态类的构造函数解析

    静态构造函数是C#的一个新特性,其实好像很少用到。不过当我们想初始化一些静态变量的时候就需要用到它了。这个构造函数是属于类的,而不是属于哪个实例的,就是说这个构造函数只会执行一次。静态构造函数由.NET自动调用。

    (1)静态构造函数既没有访问修饰符,也没有参数。因为是.NET调用的,所以像public和private等修饰符就没有意义了。

    (2).NET将自动调用静态构造函数来初始化类,也就是说我们无法直接调用静态构造函数,也就无法控制什么时候执行静态构造函数了。

    (3)一个类只能有一个静态构造函数。

    (4)如果没有写静态构造函数,而类中包含带有初始值设定的静态成员,那么编译器会自动生成默认的静态构造函数。

  3、静态类的生命周期生命周期

    当加载引用静态类的程序时,.NET Framework 公共语言运行时 (CLR) 将加载该静态类的类型信息,程序不能指定加载静态类的确切时间。但是,可以保证在程序中首次引用该类前加载该类,初始化该类的字段并调用其静态构造函数。 静态构造函数仅调用一次,在程序驻留的应用程序域的生存期内,静态类一直保留在内存中。也就是说,当页面第一次被访问的时候,相当于页面被构造,静态变量被静态构造器初始化,然后再次访问这个页面的时候,虽然非静态资源重新被构造,但是此时静态资源并不被重新构造并一直存在。

public static class StaticStudent
    {
        private static string _name;
        private static int _age;
        static StaticStudent()
        {            
        }
        
        public static string Name
        {
            get { return _name; }
            set
            {
                _name = value;
            }
        }

        public static int Age
        {
            get { return _age; }
            set
            {
                _age = value;
            }
        }
    }
View Code

三、静态成员

  1、静态成员的特性

  (1)静态成员只被创建一次,所以静态成员只有一份,实例成员有多少个对象,就有多少份。  

  (2)成员需要被共享的时候,方法需要被反复调用的时候,就可以把这些成员定义为静态成员。

  (3)在静态方法中,不能直接调用实例成员,因为静态方法被调用的时候,对象还有可能不存在。

  (4)this/base 关键字在静态方法中不能使用,因为有可能对象还不存在。

  (5)在实例方法中,可以调用静态成员,因为这个时候静态成员肯定存在。

  (6)非静态类可以包含静态的方法、字段、属性或事件;

  (7)一个非静态类既有静态成员也有实例成员,无论对一个类创建多少个实例,它的静态成员都只有一个副本;  

  (8)静态方法只能被重载,而不能被重写,因为静态方法不属于类的实例成员;

  (9)静态类不能够被继承,原因你可以理解为静态类被编译后其实就是抽象类和密封类,也可以这样理解:继承后 实例化对象的时候会先初始化基类构造函数 而基类没有非静态构造函数。

  (10)静态类不能实现接口。这时你会问我静态类被编译的结果是abstract和sealed类,接口是abstract类,这并没有影响到方法的实现啊。举个例子我们定义一个静态类,我们知道在一静态类中是不能定义实例化的成员的(比如实例化的方法)。一个类实现一个接口必须要用实例的方法来实现接口中的定义的契约,这个与上面的矛盾。

  (11)静态类不能被派生,原因是静态类只能从System.Object派生,派生继承是OO的,静态是反OO的。

  2、生命周期

  静态成员在第一次被访问之前并且在调用静态构造函数(如有存在)之前进行初始化,此后一直保持在内存中,直到应用程序域的生命周期结束。

public class Student
    {
        private static string _name;
        private int _age;
        public Student(string name,int age)
        {
            this.Age = age;
            Name = name;
        }

        public static string Name
        {
            get { return _name; }
            set
            {
                _name = value;
            }
        }

        public int Age
        {
            get { return _age; }
            set
            {
                _age = value;
            }
        }

        public static void StaticPrint()
        {
            Console.WriteLine("静态方法{0}",Name);
        }
        public void Print()
        {
            Console.WriteLine("非静态方法{0} {1}",Name,Age);
        }
    }
View Code
原文地址:https://www.cnblogs.com/qtiger/p/11176143.html