跳转到内容

C Sharp 属性访问器

来自代码酷
Admin留言 | 贡献2025年4月29日 (二) 18:40的版本 (Page creation by admin bot)

(差异) ←上一版本 | 已核准修订 (差异) | 最后版本 (差异) | 下一版本→ (差异)

C#属性访问器[编辑 | 编辑源代码]

属性访问器(Property Accessors)是C#中控制对类字段进行安全读写操作的特殊方法,通过getset关键字定义。它们封装了字段的访问逻辑,是面向对象编程中封装性的核心实现方式之一。

基本概念[编辑 | 编辑源代码]

属性访问器由以下两部分组成:

  • get访问器:读取属性值时调用(相当于字段的读取方法)
  • set访问器:设置属性值时调用(相当于字段的赋值方法)

基础语法结构:

public 数据类型 属性名
{
    get { return 字段; }  // 读取逻辑
    set { 字段 = value; } // 赋值逻辑(value为隐式参数)
}

访问器类型对比[编辑 | 编辑源代码]

访问器类型 功能 是否必须
get 返回值 可选(只写属性需标记为set-only)
set 赋值操作 可选(只读属性需标记为get-only)

基础示例[编辑 | 编辑源代码]

以下示例展示包含完整访问器的属性:

private string _name; // 私有字段(backing field)

public string Name
{
    get { return _name; }
    set { _name = value; } // value是编译器自动生成的上下文关键字
}

使用效果:

var obj = new MyClass();
obj.Name = "Alice";  // 调用set访问器
Console.WriteLine(obj.Name); // 调用get访问器,输出"Alice"

高级用法[编辑 | 编辑源代码]

自动实现属性[编辑 | 编辑源代码]

C# 3.0+支持简写语法(编译器自动生成隐藏字段):

public int Age { get; set; } // 自动生成私有字段

访问修饰符控制[编辑 | 编辑源代码]

可对访问器单独设置可见性:

public string ID { get; private set; } // 外部只读,类内可写

表达式体属性[编辑 | 编辑源代码]

C# 6.0+支持Lambda风格简写:

public string Greeting => $"Hello, {Name}"; // 只读属性

初始化器语法[编辑 | 编辑源代码]

C# 6.0+允许属性初始化:

public DateTime Created { get; } = DateTime.Now; // 只读初始化

验证逻辑示例[编辑 | 编辑源代码]

属性访问器的核心价值在于添加业务逻辑:

private int _score;
public int Score 
{
    get => _score;
    set 
    {
        if (value < 0 || value > 100)
            throw new ArgumentOutOfRangeException("分数必须在0-100之间");
        _score = value;
    }
}

性能考量[编辑 | 编辑源代码]

属性访问器会被JIT编译器内联优化(inline),其性能与直接字段访问几乎相同。但包含复杂逻辑的访问器会失去内联机会。

设计模式应用[编辑 | 编辑源代码]

观察者模式实现[编辑 | 编辑源代码]

通过属性触发状态变更通知:

public class Subject
{
    private string _state;
    
    public string State
    {
        get => _state;
        set 
        {
            _state = value;
            NotifyObservers(); // 值变更时自动通知观察者
        }
    }
}

延迟加载模式[编辑 | 编辑源代码]

private ExpensiveObject _expensive;
public ExpensiveObject Expensive
{
    get
    {
        if (_expensive == null)
            _expensive = InitializeExpensiveObject();
        return _expensive;
    }
}

编译器处理机制[编辑 | 编辑源代码]

属性访问器会被编译为IL代码中的特殊方法:

classDiagram class PropertyExample { -_name : string +get_Name() string +set_Name(string) void }

实际生成的IL方法名为:

  • get_PropertyName
  • set_PropertyName

最佳实践[编辑 | 编辑源代码]

1. 优先使用自动属性简化代码 2. 需要验证/转换逻辑时使用完整属性 3. 集合属性应返回副本或只读集合 4. 避免在访问器中执行耗时操作 5. 线程敏感场景需添加同步锁

常见问题[编辑 | 编辑源代码]

为什么不用公共字段?[编辑 | 编辑源代码]

  • 无法后续添加验证逻辑
  • 不支持数据绑定
  • 不利于版本控制(字段改为属性会导致二进制不兼容)

循环调用问题[编辑 | 编辑源代码]

错误示范:

public string BadExample
{
    get { return BadExample; } // 栈溢出!
    set { BadExample = value; } // 无限递归
}

正确做法应始终使用独立的支持字段(backing field)。