<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();
}
}
}