C#构造函数

    C#构造函数是一种特殊的成员函数,它主要用于为对象分配存储空间,对数据成员进行初始化.

    (1)C#构造函数的名字必须与类同名;

    (2)C#构造函数没有返回类型,它可以带参数,也可以不带参数;

    (3)C#构造函数的主要作用是完成对类的初始化工作;

    (4)在创建一个类的新对象(使用new关键字)时,系统回自动调用给类的构造函数初始化新对象;

    C#的类有两种构造函数:实例构造函数和静态构造函数

    C#构造函数之实例构造函数:

    负责初始化类中的实例变量,它只有在用户用new关键字为对象分配内存时才被调用,而且作为引用类型的类,其实例化后的对象必然时分配在托管堆(Managed Heap)上。实例构造函数又分为默认构造函数和非默认构造函数,注意一旦类有了自己的构造函数,无论是有参数还是没有参数,默认构造函数都将无效,而且仅仅声名一个类而不实例化它,则不会调用构造函数。

    C#构造函数之静态构造函数:

    (1)用于对静态字段、只读字段等的初始化;

    (2)添加static关键字,不能添加访问修饰符,因为静态构造函数都是私有的;

    (3)类的静态构造函数在给定应用程序域中至多执行一次,只有创建类的实例或者引用类的任何静态成员才激发,不能带又参数;

    (4)静态构造函数是不可继承的,而且不能被直接调用;

    (5)如果类中包含用来开始执行的 Main 方法,则该类的静态构造函数将在调用 Main 方法之前执行.任何带有初始值设定项的静态字段,则在执行该类的静态构造函数时,先要按照文本顺序执行那些初始值设定项;

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

    一个类可以同时拥有实例构造函数和静态构造函数,这是惟一可以具有相同参数列表的同名方法共存的情况。

 

 

深入代码分析

 

构造函数是可以将类型实例初始化为有效状态的特殊方法。构造函数在元数据中通常用.ctor来表示,通过IL代码可以看到。在创建一个类型的实例时,通常分为三步:

1 为实例的数据字段分配内存。

2 创建对象指针和同步索引块。

3 调用类型的实例构造器来设置对象的初始状态。

    引用类型的实例构造器

    在创建一个引用类型的对象是,调用类型的实例构造函数之前,会将对象分配的内存做清零处理,就是说在构造函数中没有显示赋值的所有字段都将设置为0或null。

    实例构造函数和一般方法不同,他永远都不能被继承,所有以下的关键字也不能用于实例构造函数(virtual new override sealed abstract)。

    一个类中如果没有显示定义任何构造函数,C#编译器将定义一个默认的无参构造函数。

    抽象(abstract)类的默认构造函数的访问修饰符为protected。

    构造函数可以初始化字段,不过在c#语言中提供了一种简单的方法,在定义字段的时候直接赋值以初始化。如下:

1 public class User
2 {
3    private int _age = 25;
4    private string _name = "oec2003";
5 }
6

     像上面那样的确很方便,但如果有好几个已经初始化的实例字段和多个重载的构造函数同时存在的情况下,就应该将实例字段的初始化放到一个公共的构造函数中,其他的构造函数通过this来显示调用该构造函数,这样可以减少代码生成的大小,看下面的例子。

1     public abstract  class User
2      {
3         private int _age=25;
4         private string _name="oec2003";
5         private string _email = "oec2003@gmail.com";
6
7         public User(Int32 age)
8          {
9             this._age = age;
10          }
11
12         public User(string name)
13          {
14             this._name = name;
15          }
16
17         public User(Int32 age, String name, String email)
18          {
19             this._age = age;
20             this._name = name;
21             this._email = email;
22          }
23      }

     正确的写法应该像下面这样 

1     public abstract  class User
2      {
3         private int _age;
4         private string _name;
5         private string _email;
6
7         public User()
8          {
9              _age=25;
10              _name="oec2003";
11              _email = "oec2003@gmail.com";
12          }
13
14         public User(Int32 age):this()
15          {
16             this._age = age;
17          }
18
19         public User(string name):this()
20          {
21             this._name = name;
22          }
23
24         public User(Int32 age, String name, String email):this()
25          {
26             this._age = age;
27             this._name = name;
28             this._email = email;
29          }
30      }

     值类型的实例构造函数

     值类型的实例构造函数和引用类型的有很大不同,在值类型中不能含有无参的构造函数,如果显式指定无参的构造函数将会出现编译错误。如下面代码会出现编译错误:

1     struct User
2      {
3         public Int32 _age;
4         public String _name;
5
6         public User()
7          {
8              _age = 25;
9              _name = "oec2003";
10          }
11      }

     值类型不能包含无参的构造函数,也不能在值类型中给字段进行初始化,下面的代码也将不能通过编译。

1     public struct User
2      {
3         public Int32 _age=25;
4         public String _name="oec2003";
5      }

     在值类型中也可以有构造函数,不过该构造函数必须含有参数,而且要初始化所有的字段。含有参数但没有初始化所有字段的构造函数也不能通过编译。看如下代码:     由此可见如果值类型中显示包含构造函数必须要初始化所有的字段。如果有多个构造函数,每个构造函数也必须保证初始化所有的字段,否则不能通过编译。如果值类型中不包含构造函数,实例化时所有字段将设置为0或null。

1    public struct User
2      {
3         public Int32 _age;
4         public String _name;
5         //只初始化了_age
6         public User(Int32 age)
7          {
8              _age = age;
9          }
10         public User(Int32 age,String name)
11          {
12              _age = age;
13              _name = name;
14          }
15      }
16
17
18

     类型构造函数

     类 型构造函数也被称为静态构造函数。静态构造函数可以用于引用类型和值类型。和实例构造函数不同的是静态构造函数在一个类型中永远只有一个,并且不能包含参 数。静态构造函数中只能初始化静态字段。下面代码分别展示在值类型(和实力构造函数不同,值类型中允许显示定义无参的静态构造函数)和引用类型中的静态构 造函数。 

1     //值类型
2     public struct User
3      {
4         public static Int32 _age ;    
5         public static String _name;
6
7         static User()
8          {
9              _age = 25;
10              _name = "oec2003";
11          }
12      }
13     //引用类型
14     public class User
15      {
16         public static Int32 _age ;    
17         public static String _name;
18
19         static User()
20          {
21              _age = 25;
22              _name = "oec2003";
23          }
24      }

     为了防止开发人员编写的代码调用静态构造函数,C#编译器会将静态构造函数定义为私有(private)的,并且不能显示地给静态构造函数添加访问修饰符,如果这么做了会出现编译错误。

    上面讲到过在值类型中不能在定义是给实例字段赋值,否则会编译错误,但可以在定义时给静态字段赋值,看下面代码:

1    public struct User
2     {
3        public static Int32 _age = 25;    //正确 可以初始化静态字段
4         public String _name = "oec2003";  //错误 不能初始化实例字段
5      }
6

  

     静态构造函数不应该去调用基类的静态构造函数,因为静态字段是不会被继承到子类中,所以这样做没有意义。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值