构造器(C#)

一个东西的出现自然是有原因的,就像构造器一样。那为什么会有构造器呢?

首先,类都有默认的构造器,不管你是否显示定义。当我们要读取或赋值类中的属性时,需要先用new操作符实例化一

个类的对象,然后再进行操作。

假如这么一个情况:你实例化类的对象之后,忘了给字段赋值了,而字段恰好没在声明时进行赋值,那么实例化的对

象并没有了实质的意义,因为里面是无效的字段,字段并没有值。一旦这种情况发生的多了,编译器也不警告,那么

会无缘无故占用内存空间,而且让代码很难读懂。


针对以上问题,往往我们没必要依赖默认构造器,我们大可显式定义默认构造器,提供在创建对象时指定必需的数

据。定义构造器就是创建一个方法名与类名完全相同的方法,且方法没有返回类型。

那么有这样一个情形,一个字段在声明时进行了赋值,在构造器内部也进行了赋值。那么最终字段的值以哪个为准

呢?代码执行的顺序是,声明时赋值之后,构造器内部赋值再发生;也就是说构造器赋值会覆盖字段声明时的赋值,

最终生效的是构造器赋值。


与构造器相关的还有对象初始化器(对象初始化列表)和集合初始化器。另外构造器还可以重载,而比构造器重载好一

些的是使用带有附加参数的构造器,可以使用可选参数来替代重载,这样也可以清除地看出"默认"属性的默认值。

有时候在构造器重载时,发现大量的代码都是重复的,所以维护起来也不方便。而完全可以在一个构造器中调用另一

个构造器,避免重复的代码。这样的想法可以用构造器初始化器来实现,成为构造器链。初始化器会在执行当前构造

器实现之前,判断调用另外的哪一个构造器。


请看下面一个例子:

public ConstructorExample()
{
    this.InitializeComponent();

    Phone phone1 = new Phone("Microsoft",3499);
    txtblk1.Text = string.Format("手机1的品牌和价格分别是:{0},{1}元",phone1.Brand,phone1.Price);

    //对象初始化器,格式是在构造器后添加一对{},大括号里添加构造器里的属性之外的成员属性,进行初始化
    Phone phone2 = new Phone("Nokia", 1799) { MemorySize = "8G",ScreenSize = 5};
    txtblk2.Text = string.Format("手机2的品牌和价格分别是:{0},{1}元", phone2.Brand, phone2.Price);
    txtblk3.Text = string.Format("手机2的容量和屏幕分别是:{0},{1}寸", phone2.MemorySize, phone2.ScreenSize);

    //利用构造器链定义的构造函数
    Phone phone3 = new Phone("HTC", 6, "32G", 2399);
    txtblk4.Text = string.Format("手机3的品牌和价格分别是:{0},{1}元", phone3.Brand, phone3.Price);
    txtblk5.Text = string.Format("手机3的容量和屏幕分别是:{0},{1}寸", phone3.MemorySize, phone3.ScreenSize);

    //在下面的构造函数中并没有显式定义phone4对象的MemorySize值,但依旧能输出MemorySize值为16G
    Phone phone4 = new Phone("BlackBerry", 4.0);
    txtblk6.Text = string.Format("手机3的品牌,屏幕和容量分别是:{0},{1}寸,{2}", phone4.Brand, phone4.ScreenSize,phone4.MemorySize);

    Phone phone5 = new Phone("BlackBerry", 4, "4G");
    txtblk7.Text = string.Format("手机3的品牌,屏幕和容量分别是:{0},{1}寸,{2}", phone5.Brand, phone5.ScreenSize, phone5.MemorySize);

    //集合初始化器
    List<Phone> phones = new List<Phone>()
    {
        new Phone("Microsoft",3499),
        new Phone("Nokia",1799),
        new Phone("HTC",6,"32G",2399),
        new Phone("BlackBerry",4.0),
        new Phone("BlackBerry", 4, "4G")
};
}

class Phone
{
    public string Brand { get; set; }
    public double ScreenSize { get; set; }
    public string MemorySize { get; set; }
    public int Price { get; set; }
    public Phone(string brand,int price)
    {
        Brand = brand;
        Price = price;
    }

    //构造函数链格式-this:(参数1,参数2...)
    public Phone(string brand,double screenSize,string memorySize,int price):this(brand,price)
    {
        ScreenSize = screenSize;
        MemorySize = memorySize;
    }
    //在一些情况下利用可选参数来代替函数重载更为简洁有效
    public Phone(string brand,double screenSize,string memorySize="16G")
    {
        Brand = brand;
        ScreenSize = screenSize;
        MemorySize = memorySize;
    }
}

结果截图:

猜你喜欢

转载自blog.csdn.net/u010792238/article/details/50816947