C# --- Field and Property
- 字段 (Field) vs. 属性 (Property)
- Property的声明初始化方法
- 单例类property错误初始化导致线程泄漏
字段 (Field) vs. 属性 (Property)
字段 (Field) - 数据的存储容器
- 字段是直接在类或结构中声明的变量。它是存储数据的地方,是对象状态的核心组成部分。
- 目的:纯粹用于数据存储。
- 访问控制:通过访问修饰符(如 public, private, internal) 来控制谁可以访问这个存储容器。
- 关键点:根据面向对象的最佳实践,字段应该几乎总是 private 的,将其视为类的内部实现细节。将其暴露为 public 破坏了封装性,是不推荐的做法。
public class Person
{// 私有字段 - 正确的做法private string _name;private int _age;// 公共字段 - 极其不推荐!任何代码都可以随意修改,无法控制。public string NickName;
}
属性 (Property) - 数据的访问控制器
- 属性是一种特殊的类成员,它提供了对私有字段进行读取、写入或计算的灵活机制。它本质上是两个特殊方法(get 和 set 访问器)的包装。
- 目的:控制对字段的访问。它对外提供一个像字段一样简单的访问接口,但在内部你可以实现复杂的逻辑。
- 优势:
- 封装:将数据的存储(私有字段)和数据的访问(公共属性)分离。
- 数据验证:可以在 set 访问器中验证数据的有效性。
- 计算能力:可以在 get 访问器中返回计算后的值。
- 精细访问控制:可以分别设置 get 和 set 的访问级别。
public class Person
{// 私有后备字段 (Private backing fields)private string _name;private int _age;// 公共属性 (Public Properties)public string Name{get { return _name; }set {if (!string.IsNullOrWhiteSpace(value))_name = value;}}public int Age{get { return _age; }set {if (value >= 0 && value <= 120) // 数据验证_age = value;elsethrow new ArgumentException("Invalid age.");}}// 计算属性:没有后备字段,值由其他字段计算得出public string Description{get { return $"{Name} is {Age} years old."; }}
}
Property的声明初始化方法
完整属性声明(Full Property)
- 这是最传统、最详细的属性声明方式,显式地定义了后备字段和访问器逻辑。
private string _name; // 后备字段public string Name
{get { return _name; }set { _name = value; }
}
自动属性(Auto-Implemented Property)
- C# 3.0 引入的简洁语法,编译器会自动生成隐藏的后备字段。
public string Name { get; set; }
只读自动属性(Read-Only Auto-Property)
- C# 6.0 引入的语法,只能在构造函数中初始化。
public string Id { get; } // 只能在构造函数中赋值public MyClass(string id)
{Id = id;
}
自动属性初始化器(Auto-Property Initializer)
- C# 6.0 引入,允许在声明时为自动属性提供默认值。
public string Name { get; set; } = "Unknown";
public int Age { get; set; } = 18;
public List<string> Items { get; set; } = new List<string>();
表达式主体属性(Expression-Bodied Property)
- C# 7.0 引入,使用 Lambda 表达式语法 (=>) 定义只读属性。
public string FullName => $"{FirstName} {LastName}";
public double Area => Width * Height;
public bool IsValid => !string.IsNullOrEmpty(Name) && Age > 0;
Init-only 属性(Init-Only Property)
- C# 9.0 引入,允许在对象初始化期间设置属性值,之后变为只读。
public string Name { get; init; }
public int Age { get; init; }// 使用对象初始化器
var person = new Person { Name = "Alice", Age = 25 };
具有不同访问级别的属性
- 可以为 get 和 set 访问器设置不同的访问修饰符。
// 公共获取,内部设置
public string Name { get; internal set; }// 公共获取,私有设置
public int Age { get; private set; }// 受保护的获取,私有设置
public string Details { get; protected set; }
单例类property错误初始化导致线程泄漏
单例类property错误初始化导致线程泄漏