C#中是否存在只读数组接口(如IReadOnlyArray<T>)?能否扩展Array类?
C# 实现只读数组的实用方案
1. 原生自带的只读接口:IReadOnlyList<T>
C# 里没有专门的IReadOnlyArray<T>接口,但所有数组类型天然实现了IReadOnlyList<T>——这个接口只对外开放读取相关的成员:
- 只读索引器
T this[int index] { get; } Count属性
你直接把数组以IReadOnlyList<T>类型返回就行,外部调用者只能通过这个接口读取元素,没法直接调用数组的修改方法(比如索引器赋值、Array.Resize):
// 内部维护可修改的数组 private int[] _internalNumbers = { 1, 2, 3, 4 }; // 对外暴露只读访问 public IReadOnlyList<int> GetNumbers() { return _internalNumbers; }
注意点
这种方式有个局限:如果外部调用者硬要通过强制类型转换把IReadOnlyList<T>转回int[],还是能修改原数组内容。如果你的场景不需要防范这种非常规操作,这个方案足够简单高效;要是必须绝对杜绝修改,那就得用包装器,但这会创建新对象,不符合你“保留原数组”的诉求。
2. 自定义只读接口的可行性
Array类是密封类(sealed),没法通过继承给它加自定义接口实现。你可以自己定义一个只读接口,但只能通过包装类来实现它——本质上还是包装器方案,没法直接让原生数组实现这个接口。
举个自定义接口的例子:
public interface IReadOnlyArray<T> { T this[int index] { get; } int Length { get; } }
对应的包装类:
public class ReadOnlyArrayWrapper<T> : IReadOnlyArray<T> { private readonly T[] _source; public ReadOnlyArrayWrapper(T[] source) { _source = source ?? throw new ArgumentNullException(nameof(source)); } public T this[int index] => _source[index]; public int Length => _source.Length; }
这种方式能提供严格的只读性,但还是绕不开创建包装对象,没法直接复用原数组的接口。
总结
如果只是想通过接口规范外部的访问行为,返回IReadOnlyList<T>是最省心的选择——不用额外造对象,完全利用数组原生的接口实现。要是担心外部强制转换修改,只能退而求其次用包装器,但这就牺牲了你“保留原数组”的需求,得根据实际场景权衡。
内容的提问来源于stack exchange,提问作者Yevhen Diulin
相关产品推荐
相关产品推荐

