1. 简单构造函数
构造函数 —— 这是类里的一个特殊方法,在你创建对象时会自动调用。它用来初始化(配置)对象:设置初始值、做些检查,甚至你想写个冷笑话在里面也行,说不定能让你心情好点。
构造函数让你能直接把对象创建成某种状态,而不用手动一个个字段和属性去赋值。这很方便也更安全,因为你一开始就把所有重要参数都写清楚了——不会忘了啥关键东西。
没有构造函数的话,代码会很啰嗦,还容易出错:
Person p = new Person();
p.Name = "Julia";
p.Age = 25; // 如果忘了写年龄会咋样?
有了构造函数:
Person p = new Person("Julia", 25); // 一步到位,对象直接能用了!
构造函数语法
构造函数就是一个特殊的“方法”,它的名字和类名完全一样,而且没有返回值(连void都没有)。下面是默认构造函数的样子:
public class Person
{
// 默认构造函数(无参数)
public Person()
{
// 这里可以写初始化代码
}
}
默认构造函数就像个隐形“小助手”,它不接收任何参数,只是把你类里的所有字段和属性都初始化成默认值:
- 数值类型(int、double、float等)默认是0。
- 布尔类型(bool)默认是false。
- 引用类型(string、其他类)默认是null(就是“啥都没有”,没有对象的引用)。
- DateTime默认是01.01.0001 00:00:00。
怎么调用构造函数?
其实你写new操作符创建对象时,就是在调用构造函数!
Person p = new Person();
如果你啥构造函数都没写,C#编译器会帮你自动生成一个默认构造函数(无参数)。但只要你自己写了一个构造函数,默认的那个就没了,如果还想要,得自己手动加回来。
例子
来给我们的应用加个构造函数。下面是学生类的简单版本:
public class Student
{
public string Name;
public int Age;
// 带两个参数的构造函数(名字和年龄)
public Student(string name, int age)
{
Name = name; // 给字段赋值
Age = age;
}
}
现在可以这样创建学生对象:
Student s = new Student("Joe", 21);
Console.WriteLine($"{s.Name}: {s.Age} 岁"); // Joe: 21 岁
- 我们声明了和类一样可见性的构造函数(public)。
- 构造函数里用传进来的参数给字段赋值。
- 这样能防止忘记赋值:编译器会强制你创建对象时写上名字和年龄。
2. 构造函数参数
在C#里你可以声明多个构造函数,参数列表不一样。这叫构造函数重载(方法重载以后还会讲)。
比如,加一个无参数的构造函数:
public class Student
{
public string Name;
public int Age;
// 默认构造函数
public Student()
{
Name = "无名氏";
Age = 0;
}
// 带参数的构造函数
public Student(string name, int age)
{
Name = name;
Age = age;
}
}
现在两种写法都可以:
Student s1 = new Student(); // 名字: 无名氏, 年龄: 0
Student s2 = new Student("Helga", 22); // 名字: Helga, 年龄: 22
用构造函数做校验
构造函数是个很好的地方用来检查传进来的数据靠不靠谱。比如,学生年龄不能是负数!
public Student(string name, int age)
{
if (age < 0)
throw new ArgumentException("年龄不能是负数!");
Name = name;
Age = age;
}
现在如果有人想创建Student("Malysh", -2),程序会直接抛异常(ArgumentException)。这种写法很常见,用来保证数据“铁打的靠谱”。
3. 复杂对象的初始化
实际开发里,一个对象经常不只是基本类型,还会包含别的对象:
public class Group
{
public string GroupName;
public Student[] Students;
public Group(string groupName, Student[] students)
{
GroupName = groupName;
Students = students;
}
}
现在可以很方便地创建一个带学生数组的组:
var students = new Student[]
{
new Student("Joe", 20),
new Student("Maria", 19)
};
Group g = new Group("组-101", students);
字段默认值初始化
有时候你想给某些字段设个默认值,如果构造函数参数没传的话。比如,e-mail不是必填项:
public Student(string name, int age)
{
Name = name;
Age = age;
Email = "unknown@noemail.com"; // 默认值
}
4. 用Object Initializer初始化
构造函数还能和另一种很方便的写法配合用——对象初始化器。你可以先调用构造函数,然后用花括号写上新对象的属性值:
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
// 构造函数还是推荐写
public Student(string name, int age)
{
Name = name;
Age = age;
Email = "";
}
}
Student s = new Student("Anton", 18) { Email = "anton@domain.com" }; // 构造函数+属性
这种写法和构造函数配合特别好用,尤其是有些参数有默认值或者创建时还不确定。
5. 常见错误和注意点
用构造函数时,新手经常会踩几个坑。咱们来举例说说:
错误1:名字写错
有时候参数名和字段名只差大小写,很容易搞混。
public Student(string Name, int Age) // 首字母大写!
{
Name = Name; // 哎呀!两个Name都指参数,字段没赋值。
}
正确写法: 用this指向对象的字段:
public Student(string name, int age)
{
this.Name = name;
this.Age = age;
}
或者直接用不同的名字(比如nameParam、ageParam),不过用this.是好习惯,尤其是大项目里。
错误2:没有默认构造函数
如果你写了至少一个构造函数,然后又想无参数创建对象——编译器会报错:
public class Student
{
public Student(string name) { /*...*/ }
}
// 某处代码
Student s = new Student(); // 错误!没有无参数构造函数。
解决方法: 显式加一个无参数构造函数:
public Student() { /*...*/ }
错误3:死循环——构造函数自己调用自己
public Student()
{
// 错误!自己调用自己——死循环。
new Student();
}
GO TO FULL VERSION