IReadOnlyList<T>
IReadOnlyList<T> 是 .NET 中的一个重要接口,代表一个只读的元素集合。下面是关于它的详细解释:
基本定义
1 public interface IReadOnlyList<out T> : IReadOnlyCollection<T>, IEnumerable<T> 2 { 3 T this[int index] { get; } 4 }
核心特性
1. 只读访问
-
只能读取元素,不能修改
-
没有
Add()、Remove()、Clear()等方法 -
索引器只有 getter(
this[int index])
2. 索引支持
-
可以通过从0开始的整数索引直接访问元素
-
支持随机访问,时间复杂度通常为 O(1)
3. 继承关系
1 IEnumerable<T>
2 ↓ 3 IReadOnlyCollection<T> // 添加了 Count 属性 4 ↓ 5 IReadOnlyList<T> // 添加了索引器
常见实现
内置类型
1 // 数组 2 int[] array = new int[] { 1, 2, 3 }; 3 IReadOnlyList<int> readOnlyArray = array; 4 5 // List<T>(实现了 IReadOnlyList<T>) 6 List<string> list = new List<string> { "A", "B", "C" }; 7 IReadOnlyList<string> readOnlyList = list; 8 9 // ArraySegment<T> 10 ArraySegment<int> segment = new ArraySegment<int>(array, 1, 2); 11 IReadOnlyList<int> readOnlySegment = segment;
专用只读集合
1 // ReadOnlyCollection<T>(包装器) 2 List<int> originalList = new List<int> { 1, 2, 3 }; 3 ReadOnlyCollection<int> readOnly = new ReadOnlyCollection<int>(originalList); 4 IReadOnlyList<int> readOnlyList = readOnly;
使用场景
1. API 设计
1 // 作为返回值 - 明确表示数据是只读的 2 public IReadOnlyList<string> GetLogEntries() 3 { 4 return _logEntries.AsReadOnly(); 5 } 6 7 // 作为参数 - 明确表示方法不会修改传入的集合 8 public void ProcessItems(IReadOnlyList<Item> items) 9 { 10 foreach (var item in items) 11 { 12 // 只能读取,不能修改 13 } 14 }
2. 性能优化
1 // 避免不必要的复制 2 public IReadOnlyList<T> GetSlice(int start, int count) 3 { 4 // 返回原始数据的只读视图,不复制数据 5 return new ArraySegment<T>(_data, start, count); 6 }
3. 线程安全考虑
1 // 在需要共享数据的多线程场景中 2 public class DataProcessor 3 { 4 private readonly IReadOnlyList<Data> _sharedData; 5 6 public DataProcessor(IReadOnlyList<Data> data) 7 { 8 _sharedData = data; // 多个处理器可以安全地共享只读数据 9 } 10 }
与相关接口的比较
| 接口 | 索引访问 | 修改操作 | 计数 | 主要用途 |
|---|---|---|---|---|
IEnumerable<T> |
✗ | ✗ | ✗ | 最基本枚举 |
ICollection<T> |
✗ | ✓ | ✓ | 可修改集合 |
IList<T> |
✓ | ✓ | ✓ | 可修改索引集合 |
IReadOnlyCollection<T> |
✗ | ✗ | ✓ | 只读集合 |
IReadOnlyList<T> |
✓ | ✗ | ✓ | 只读索引集合 |
最佳实践
-
优先使用 IReadOnlyList<T> 作为参数
1 // 好 - 明确表示不会修改 2 public void PrintNames(IReadOnlyList<string> names) 3 4 // 不好 - 可能被误认为会修改 5 public void PrintNames(List<string> names)
在不需要修改时返回 IReadOnlyList<T>
1 public IReadOnlyList<Customer> GetActiveCustomers() 2 { 3 return _customers.Where(c => c.IsActive).ToList(); 4 }
注意性能
1 // 如果需要频繁的随机访问,使用 IReadOnlyList<T> 2 // 如果只需要遍历,使用 IEnumerable<T> 可能更合适
与 LINQ 配合
1 IReadOnlyList<int> numbers = new List<int> { 1, 2, 3, 4, 5 }; 2 3 // LINQ 方法返回 IEnumerable<T>,如果需要 IReadOnlyList<T>: 4 IReadOnlyList<int> evenNumbers = numbers.Where(n => n % 2 == 0).ToList();
// 在需要共享数据的多线程场景中public class DataProcessor{ private readonly IReadOnlyList<Data> _sharedData; public DataProcessor(IReadOnlyList<Data> data) { _sharedData = data; // 多个处理器可以安全地共享只读数据 }}

浙公网安备 33010602011771号