You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为ReadOnlyCollection<T>实现按名称查找的自定义字符串索引器

解决方案

要实现按Animal.Name的字符串索引器,同时保持集合的只读特性且不使用字典,你可以自定义一个只读集合类,替代系统自带的ReadOnlyCollection<Animal>。系统的ReadOnlyCollection是密封类无法继承扩展,所以我们自己实现一个符合只读要求的集合,并添加自定义索引器。

步骤1:自定义只读集合类

创建一个实现IReadOnlyList<Animal>的类,内部包装你的私有List<Animal>,同时添加字符串索引器:

public class ReadOnlyAnimalCollection : IReadOnlyList<Animal>
{
    private readonly List<Animal> _innerList;

    // 构造函数,传入内部要包装的List
    public ReadOnlyAnimalCollection(List<Animal> innerList)
    {
        _innerList = innerList ?? throw new ArgumentNullException(nameof(innerList));
    }

    // 实现IReadOnlyList的int索引器
    public Animal this[int index] => _innerList[index];

    // 添加自定义字符串索引器,按Name查找
    public Animal this[string name]
    {
        get
        {
            var animal = _innerList.FirstOrDefault(a => a.Name == name);
            if (animal == null)
                throw new KeyNotFoundException($"找不到名为{name}的动物");
            return animal;
        }
    }

    // 实现IReadOnlyCollection的Count属性
    public int Count => _innerList.Count;

    // 实现IEnumerable的枚举器
    public IEnumerator<Animal> GetEnumerator()
    {
        return _innerList.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

步骤2:修改Zoo类的Animals属性

把原来的ReadOnlyCollection<Animal>替换成自定义的ReadOnlyAnimalCollection:

public class Animal
{
    public string Name { get; set; }
}

public class Zoo
{
    private List<Animal> _animals = new List<Animal>();
    // 对外暴露自定义的只读集合
    public ReadOnlyAnimalCollection Animals => new ReadOnlyAnimalCollection(_animals);

    public void AddAnimal(Animal animal)
    {
        if (animal == null)
            throw new ArgumentNullException(nameof(animal));
        _animals.Add(animal);
    }
}

步骤3:使用示例

现在你可以同时通过int索引和字符串索引访问集合:

Zoo z = new Zoo();
z.AddAnimal(new Animal() { Name = "Lion" });
z.AddAnimal(new Animal() { Name = "Tiger" });

// 通过int索引访问
var lionByIndex = z.Animals[0];
// 通过Name字符串索引访问
var tigerByName = z.Animals["Tiger"];

关键说明

  • 自定义集合完全基于原有的List<Animal>,不需要额外的字典存储,符合你的要求;
  • 集合对外只暴露只读接口(IReadOnlyList),确保外部无法修改集合内容,所有修改必须通过Zoo的AddAnimal方法;
  • 字符串索引器内部使用FirstOrDefault遍历查找,若需要忽略大小写,可以修改为a.Name.Equals(name, StringComparison.OrdinalIgnoreCase);
  • 如果不想在找不到时抛出异常,也可以改为返回null,只需去掉throw语句直接返回animal即可。

内容的提问来源于stack exchange,提问作者Andrei Popescu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 04:22:36