类属性和构造方法
1. 属性和 Backing Field#
1.1. Backing Field#
在 C# 中, 当你创建一个类的属性时, 你实际上是在创建一种访问类内部数据的方式, 而这个内部数据就存储在 backing field 中:
public class Person {
// 这是 backing field
private string _name;
// 这是属性
public string Name {
get { return _name; }
set { _name = value; }
}
}
对于backing field的命名, C#中有几种常见的约定:
private string _name; // 对应 Name 属性
private string m_name; // 对应 Name 属性, m 代表 member
private string name; // 对应 Name 属性
微软官方推荐使用下划线前缀(_name)的命名方式,这也是.NET社区中最广泛采用的规范。
1.2. Auto-implemented Properties#
C# 3.0引入了自动实现的属性, 编译器会自动生成 backing field:
public class Person {
// 编译器会自动为属性 Name 生成一个 backing field
public string Name { get; set; }
}
常见的例子:
public class Person {
private int _age;
public int Age {
get { return _age; }
set {
if (value < 0)
throw new ArgumentException("Age cannot be negative");
_age = value;
}
}
}
Backing Field 是一个私有字段, 用于存储属性的实际数据
value
是 C# 中的一个特殊关键字, 它只能在属性或索引器的 set
访问器中使用, 它代表调用者尝试分配给属性的值Person person = new Person(); person.Name = "John"; // 这里的 "John" 就是 set 访问器中的 value
1.3. 只声明 get 访问器#
Declare only the [get] accessor, which makes the property immutable everywhere except in the type’s constructor.
public class Person
{
public string Name { get; } // 只声明 get
public Person(string name)
{
Name = name; // 只能在构造函数中设置
}
}
var person = new Person("Alice");
// person.Name = "Bob"; // 错误!无法修改,因为没有 set
Console.WriteLine(person.Name); // 输出: Alice
这种方式适合需要保护数据不被外部修改的场景, 比如表示一个对象的固有属性(例如身份证号)
2. 构造函数#
2.1. 对象初始化器#
在 C# 中, 如果一个类没有显式定义任何构造函数, 编译器会自动为该类提供一个 无参的默认构造函数, 这个默认构造函数的作用是创建一个类的实例, 并将所有字段或属性初始化为它们的默认值(例如,string 初始化为 null,int 初始化为 0)
class Person {
public string Name { get; set; }
public int Age { get; set; }
public void SayHello() {
Console.WriteLine($"Hello, I am {Name}, {Age} years old.");
}
}
Person p = new Person { Name = "Bob", Age = 30 };
可是这里是什么意思呢, 创建实例的时候不是传了参数吗?
new Person()
确实调用了默认构造函数, 创建一个 Person 对象, 此时Name
是null
,Age
是0
, 但紧随其后的{ Name = "Bob", Age = 30 }
是 对象初始化器 的语法, 它允许你在对象创建后立即设置属性的值, 这实际上是 C# 提供的一种简洁写法, 相当于以下代码:Person p = new Person(); // 调用默认构造函数 p.Name = "Bob"; // 设置 Name 属性 p.Age = 30; // 设置 Age 属性
对象初始化器的工作原理是:
- 先调用类的构造函数(这里是隐式的默认构造函数)
- 然后按照初始化器中指定的顺序, 依次设置对象的公共属性或字段