属性(Properties)
属性是C#中一种特殊的成员,它提供了对类或对象字段的灵活访问机制。属性结合了字段和方法的特性,允许你在访问数据时添加逻辑验证。
属性的基本语法
public class Person
{
private string _name; // 私有字段
// 属性
public string Name
{
get { return _name; }
set { _name = value; }
}
}
自动实现属性
C#提供了简化的属性声明方式:
public class Person
{
public string Name { get; set; } // 自动实现属性
}
编译器会自动为这种属性生成一个私有字段和基本的get/set方法。
只读属性
public class Circle
{
public double Radius { get; } // 只读属性
public Circle(double radius)
{
Radius = radius;
}
}
属性验证
可以在set访问器中添加验证逻辑:
public class Person
{
private int _age;
public int Age
{
get => _age;
set
{
if (value < 0 || value > 120)
throw new ArgumentOutOfRangeException("Age must be between 0 and 120");
_age = value;
}
}
}
表达式体属性
C# 6.0引入了表达式体属性:
public class Rectangle
{
public double Width { get; set; }
public double Height { get; set; }
public double Area => Width * Height; // 表达式体属性
}
索引器(Indexers)
索引器允许类或结构的实例像数组一样被索引。当您为类定义索引器时,该类的行为类似于虚拟数组。
基本索引器语法
public class StringCollection
{
private string[] _strings = new string[10];
// 索引器
public string this[int index]
{
get => _strings[index];
set => _strings[index] = value;
}
}
使用示例:
var collection = new StringCollection();
collection[0] = "Hello"; // 使用索引器设置值
Console.WriteLine(collection[0]); // 使用索引器获取值
多参数索引器
索引器可以有多个参数:
public class Matrix
{
private double[,] _data = new double[10, 10];
public double this[int row, int column]
{
get => _data[row, column];
set => _data[row, column] = value;
}
}
使用示例:
var matrix = new Matrix();
matrix[0, 0] = 1.0;
Console.WriteLine(matrix[0, 0]);
字符串索引器
索引器不仅限于整数参数:
public class Dictionary
{
private Dictionary<string, string> _dictionary = new Dictionary<string, string>();
public string this[string key]
{
get => _dictionary[key];
set => _dictionary[key] = value;
}
}
表达式体索引器
C# 7.0开始支持表达式体索引器:
public class SampleCollection
{
private string[] arr = new string[100];
public string this[int i]
{
get => arr[i];
set => arr[i] = value;
}
}
属性和索引器的比较
特性 | 属性 | 索引器 |
---|---|---|
访问方式 | 通过名称访问 | 通过索引访问 |
参数 | 无参数 | 可以有一个或多个参数 |
重载 | 不能重载 | 可以重载 |
用途 | 访问单个数据成员 | 访问集合中的元素 |
语法 | public int Prop { get; set; } | public int this[int index] { get; set; } |
实际应用示例
public class ShoppingCart
{
private List<Product> _products = new List<Product>();
// 只读属性,返回购物车中商品数量
public int ItemCount => _products.Count;
// 只读属性,计算总价
public decimal TotalPrice => _products.Sum(p => p.Price * p.Quantity);
// 索引器,通过产品ID访问
public Product this[int productId]
{
get => _products.FirstOrDefault(p => p.Id == productId);
}
// 索引器,通过产品名称访问
public Product this[string productName]
{
get => _products.FirstOrDefault(p => p.Name == productName);
}
public void AddProduct(Product product)
{
var existing = _products.FirstOrDefault(p => p.Id == product.Id);
if (existing != null)
existing.Quantity += product.Quantity;
else
_products.Add(product);
}
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
}
总结
- 属性提供了一种安全、灵活的方式来访问类的字段,可以在访问时添加验证逻辑
- 索引器让类的实例可以像数组或集合一样被索引访问
- 两者都可以使用表达式体语法简化代码
- 索引器支持重载,可以根据不同的参数类型提供不同的访问方式
- 合理使用属性和索引器可以提高代码的可读性和安全性
属性和索引器是C#中强大的特性,它们使你的类更加直观易用,同时保持了良好的封装性。在设计类时,考虑使用这些特性来提供更优雅的API。