C Sharp 属性基础
外观
C#属性基础[编辑 | 编辑源代码]
介绍[编辑 | 编辑源代码]
在C#中,属性(Property)是一种特殊的类成员,它提供了一种灵活的方式来读取、写入或计算私有字段的值。属性是字段(field)的自然扩展,既保持了数据的封装性,又允许通过访问器(accessors)控制对数据的访问逻辑。
属性通常由以下部分组成:
- 一个可选的访问修饰符(如
public
,private
) - 属性类型(如
int
,string
) - 属性名称
get
访问器(用于读取值)set
访问器(用于写入值)
基本语法[编辑 | 编辑源代码]
属性的标准声明格式如下:
[access-modifier] [type] [property-name]
{
get { /* 返回属性值 */ }
set { /* 设置属性值 */ }
}
示例1:简单属性[编辑 | 编辑源代码]
public class Person
{
private string _name; // 私有字段
// Name属性
public string Name
{
get { return _name; }
set { _name = value; } // 'value'是隐式参数
}
}
属性类型[编辑 | 编辑源代码]
1. 自动实现属性[编辑 | 编辑源代码]
C# 3.0引入的简写语法,编译器会自动生成私有字段:
public class Product
{
public int Id { get; set; } // 自动属性
public decimal Price { get; set; }
}
2. 只读属性[编辑 | 编辑源代码]
只有get访问器的属性:
public class Circle
{
public double Radius { get; } = 5.0; // 初始化后不可修改
}
3. 计算属性[编辑 | 编辑源代码]
基于其他值动态计算的属性:
public class Rectangle
{
public double Width { get; set; }
public double Height { get; set; }
public double Area
{
get { return Width * Height; } // 计算得出
}
}
访问器控制[编辑 | 编辑源代码]
可以通过访问修饰符对get/set分别控制:
public class BankAccount
{
public decimal Balance { get; private set; } // 外部只读
public void Deposit(decimal amount)
{
Balance += amount; // 类内部可修改
}
}
属性 vs 字段[编辑 | 编辑源代码]
特性 | 属性 | 字段 |
---|---|---|
支持 | 不支持 | ||
可分别控制get/set | 统一访问级别 | ||
可包含 | 不能包含 | ||
必须显式设置 | 有类型默认值 |
实际应用案例[编辑 | 编辑源代码]
数据验证示例[编辑 | 编辑源代码]
public class Student
{
private int _age;
public int Age
{
get => _age;
set
{
if (value < 0 || value > 120)
throw new ArgumentOutOfRangeException("年龄必须在0-120之间");
_age = value;
}
}
}
INotifyPropertyChanged 实现[编辑 | 编辑源代码]
在WPF/MVVM中的典型应用:
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
public class User : ObservableObject
{
private string _username;
public string Username
{
get => _username;
set
{
_username = value;
OnPropertyChanged(); // 通知UI更新
}
}
}
高级主题[编辑 | 编辑源代码]
索引器属性[编辑 | 编辑源代码]
允许类实例像数组一样被索引:
public class StringArray
{
private string[] _array = new string[10];
public string this[int index]
{
get => _array[index];
set => _array[index] = value;
}
}
表达式体属性[编辑 | 编辑源代码]
C# 6+支持的简写语法:
public class Point
{
public int X { get; set; }
public int Y { get; set; }
public string Coordinates => $"({X}, {Y})"; // 表达式体属性
}
属性初始化顺序[编辑 | 编辑源代码]
最佳实践[编辑 | 编辑源代码]
1. 对公有成员总是使用属性而非字段 2. 简单的get/set操作使用自动属性 3. 需要验证或计算时使用完整属性 4. 考虑对set访问器添加保护 5. 避免在属性getter中执行耗时操作
数学关系[编辑 | 编辑源代码]
属性可以看作是两个函数的组合:
其中和分别对应get和set访问器的逻辑。