<1>
构造函数分为:实例构造函数,和静态构造函数。
非静态类中可以有静态方法,但是静态类中只能是静态方法,不能有非静态方法。
实例构造函数:使用 new 表达式创建某个类的对象时,会使用实例构造函数创建和初始化所有实例成员变量。或用于执行仅需执行一次的特定操作。 所以它的实际作用就是初始化对象的成员变量。
静态构造函数:静态构造函数用于初始化任何静态数据,或用于执行仅需执行一次的特定操作。如果一个类存在静态成员,那么在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数。所以静态构造函数的作用和实例构造函数的作用差不多,即用户初始化静态成员变量。
1>当申明一个静态变量,同时又给它赋值的时候。这个赋值将会在静态类的构造函数前先被执行。等这个赋值完毕后在执行构造函数。
using System; using System.Text; namespace 静态构造函数的执行顺序 { class Employee { static Employee() //声明NextId并给它赋了初值42后,会跳到静态构造函数这里来。接着又是给NextId赋了一个随机数的值 { NextId = 50; } public static int NextId = 42; //当申明一个静态变量,同时又给它赋值的时候。这个赋值将会在静态类的构造函数前先被执行。所有此时的NexId的值为42 等这个赋值完毕后在执行构造函数。 } class Test { static void Main(string[] args) { Console.WriteLine(Employee.NextId); //这里输出:50 Console.ReadKey(); } } }
下面是构造函数的作用(初始化对象的成员变量),及构造函数的参数传递,及构造函数的重载。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Test2 { public class Student { public Student() { } //这里接收new Student("黄雪辉", 24, '女', "广东省广州市天河区") 传递过来的值,对对象的属性或者字段进行初始化 public Student(string name, int age, char gender, string address) { this.Name = name; //初始化Name属性 //注意:this 代表当前类的对象。注意是“对象” this.Age = age; //初始化Age属性 this.Gender = gender; //初始化Gender字段 this.Address = address; //初始化Address字段 } public string Name { get; set; } public int Age { get; set; } public char Gender; public string Address { get; set; } } class Program { static void Main(string[] args) { //Student s = new Student();//在我们创建对象的时候,即new Student();的时候 ,会首先跳到 public Student(){}这个构造函数这里来,执行完构造函数后在执行我们下面的对象属性的初始化。 即:创建对象的时候一定会最先执行构造函数。既然这样,那我们就可以把对象的初始化代码放到构造函数中去(对象初始化:即将对象类的非静态的属性,或者字段赋初值) //s.Name = "黄雪辉"; //s.Age = 24; //s.Gender = '女'; //s.Address = "广东省广州市天河区"; Student s = new Student("黄雪辉", 24, '女', "广东省广州市天河区");//既然要在构造函数中初始化对象,那么我们就要将对象要初始化的值传递到构造函数中。【当我们把鼠标移动到new Student()这里的时候,我们会发现这个Student后面的括号其实就是执行构造函数】这样就把我们要初始化对象的值传递到了构造函数中。 } } }
new 关键字的作用。创建一个对象的时候,new关键字帮我们做了什么事情?
using System; using System.Text; namespace New关键字 { public class Person { } class Program { static void Main(string[] args) { //创建对象的时候会执行构造函数。 Person p = new Person(); //这里创建了一个对象。 //创建对象用new关键字。那么这个new到底为我们做了什么呢? 有以下3步 // 1,在内存中开辟一块空间。 // 2, 在开辟的空中中创建对象。 // 3,调用对象的构造函数进行初始化对象。 //这3步,如果有一步完不成,你这个对象就创建不出来。所以构造函数的访问修饰符必须是public 。如果构造函数的访问修饰符是private的话,出了Person类。在外面new Person()就无法调用构造函数。无法调用构造函数就无法创建对象了。 } } }
=================================================================================================
下面是构造函数的定义。及实例
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 构造函数 { class Person { public string Name { get; set; } public int Age { get; set; } public Person() //这儿是默认的构造函数,可以不写。构造函数也可以构成重载,一下两个函数就是重载的构造函数。构造函数没有返回值,连void都不能写,构造函数名与类名一致。构造函数就是在创建对象的同时,给它初始化 即:它通常初始化新对象的数据成员 这就是构造函数的意义。 { Name = "未命名"; Age = 0; } public Person(string name, int age) //两个参数的重载构造函数 { Name = name; Age = age; } public Person(int age) //一个参数的重载构造函数 { Age=age; } } class Program { static void Main(string[] args) { Person p1 = new Person(); Person p2 = new Person("小米", 20); Person p3 = new Person(30); Console.WriteLine("姓名是{0},年龄是{1}", p1.Name, p1.Age); //输出姓名是未命名,年龄是0 Console.WriteLine("姓名是{0},年龄是{1}", p2.Name, p2.Age); //输出姓名是小米,年龄是20 Console.WriteLine("姓名是{0},年龄是{1}", p3.Name, p3.Age); //输出姓名是,年龄是30 Console.ReadKey(); } } }
<2>
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Class1 { private static int count = 0; //在整个类加载完成之后,就初始化静态(静态变量,静态块), 一个类中只要有静态变量,就会先初始化静态变量,这时候就会调用static Class1()静态构造函数, private int ni; private static int count2 = 2; static Class1() { count++; //0自增后为1 这时候count=1 count2++; } public Class1() { count++; } static void Main(string[] args) { Class1 o1 = new Class1(); //这时候创建了一个o1对象,然后调用public Class1()构造函数 count再自增一次,变为2 Class1 o2 = new Class1();//接着这时候有创建了一个o2对象。然后再次调用public Class1()构造函数。count再次自增一次,变为3 Console.WriteLine(count); //输出3 Console.ReadKey(); } } }
<3>
================================下面有两道题目。我没对比看看
A //编译器在编译的时候,会事先分析所需要的静态字段,如果这些静态字段所在的类有静态的构造函数,则忽略字段的初始化,否则先进行静态字段的初始化。对类的静态成员初始化的顺序取决于在Main函数中的引用顺序,先引用到的先进行初始化,但如果类的静态成员的初始化依赖于其它类的静态成员,则会先初始化被依赖类的静态成员。而带有静态构造函数的类的静态字段,只有在引用到的时候才进行初始化。 using System; using System.Text; namespace Test { public class A { public static int X; //int 的默认值就是0 所有X在没有调用静态构造函数static A(){}构造函数前默认值就是0 static A() //一个类既如果存在静态字段,那么就一定会调用静态类的静态构造函数。那么现在开始进入静态构造函数 A() ;A()函数中引用了B类中的静态字段Y。那么现在有跳到了B.Y { X = B.Y + 1; //因为这里引用了B类中的静态Y字段。经过Y这个静态字段初始化完毕后,得知Y的值为1 所有此时X=1+1; 所以经过构造函数A()的执行完毕后。X此时的值已经为2了。 } } public class B { public static int Y = A.X+1; //注意A类的static构造函数还没有执行完的时候就跳到这里来了。A.X的值此时依然为0 Y=0+1 即 Y这个静态函数没有调用静态构函数B(){}的时候,Y的值已经为1了。 static B()// 一个类中如果存在静态字段,那么就一定会调用静态构造函数,声明静态变量Y后,并给Y赋l了A.X+1这个值后,那么现在就进入静态构造函数B()中;B()函数中什么代码也没有。所有此时的Y的值依然为1 。静态字段Y初始化完毕后(及静态构造函数执行完毕后)。又跳到了A类的 静态构造函数A()中了。 { } } class Program { static void Main(string[] args) { Console.WriteLine("X={0},Y={1}", A.X, B.Y); //所以这里输出 X=2,Y=1 Console.ReadLine(); } } } B 注意。B类中是没有静态构造函数的哦。因为B类没有静态构造函数,所有它最新进行静态字段的初始化 using System; using System.Text; namespace Test { public class A { public static int X; //int 的默认值就是0 所有X在没有调用静态构造函数static A(){}构造函数钱默认值就是0 static A() { X = B.Y + 1; } } //编译器在编译的时候,会事先分析所需要的静态字段,如果这些静态字段所在的类有静态的构造函数,则忽略字段的初始化,否则先进行静态字段的初始化。对类的静态成员初始化的顺序取决于在Main函数中的引用顺序,先引用到的先进行初始化,但如果类的静态成员的初始化依赖于其它类的静态成员,则会先初始化被依赖类的静态成员。而带有静态构造函数的类的静态字段,只有在引用到的时候才进行初始化。 public class B { public static int Y = A.X + 1; //因为B类中没有静态构造函数,所以先进行静态字段的初始化。我们知道,int的默认值为0 所以Y没有完成初始化前,Y的值是0; 这里给Y初始化的时候引用了A类中的静字段X ,既然引用了A类中的静态字段X ,我们知道一个类中有静态字段,静态字段是最先被初始化的。所有既然要初始化X就会调用A类的静态构造函数A() X=B.Y+1 因为B.Y没有被初始化前的默认值是0 所以X=0+1; 即 X=1 。等X初始化完毕后。我们在来完成初始化B.Y 因为Y=A.X+1 现在A.X初始化完毕了。得知A.X=1 那么Y=A.X+1即Y=1+1 所有Y=2了 public B() { } } class Program { static void Main(string[] args) { Console.WriteLine("X={0},Y={1}", A.X, B.Y); //所以这里输出 X=1,Y=2 Console.ReadLine(); } } }