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

C#:类持有List<Banana>时,如何在只读接口暴露List<IBananaRead>?

实现只读接口的列表映射(无需维护重复列表)

需求背景

为Box类创建只读接口IBoxRead,Box内部依赖List<Banana>处理所有操作;Banana类对应只读接口IBananaRead。需满足:

  • IBoxRead对外暴露IBananaRead类型的集合,而非Banana实例
  • 禁止维护两个重复的列表
  • 支持两种交互:
    • 只读权限类遍历IBananaRead调用ReadTheBanana()
    • 编辑权限类遍历Banana调用EditTheBanana()

初始代码示例

class Box : IBoxRead
{
    List<Banana> bananas;
}

interface IBoxRead
{
    List<IBananaRead> bananas;
}

不认可的方案(维护重复列表)

该方案需同步两个列表,易引发数据不一致,因此被否决:

class Box : IBoxRead
{
    List<Banana> bananas;
    List<IBananaRead> bananaReads;
}

interface IBoxRead
{
    List<IBananaRead> bananaReads;
}

正确实现方案

1. 定义基础接口与实体类

确保Banana实现IBananaRead,分离只读与编辑方法:

public interface IBananaRead
{
    void ReadTheBanana();
}

public class Banana : IBananaRead
{
    public void ReadTheBanana()
    {
        // 只读逻辑实现
    }

    public void EditTheBanana()
    {
        // 编辑逻辑实现
    }
}

2. 实现只读接口与Box类

将IBoxRead的集合改为IReadOnlyList<IBananaRead>(避免外部修改),通过自定义包装类映射原List<Banana>,无需维护重复列表:

public interface IBoxRead
{
    IReadOnlyList<IBananaRead> Bananas { get; }
}

public class Box : IBoxRead
{
    private readonly List<Banana> _bananas = new List<Banana>();

    // 对外暴露只读集合,通过包装类映射原列表
    public IReadOnlyList<IBananaRead> Bananas => new ReadOnlyBananaWrapper(_bananas);

    // 给编辑权限类提供原列表访问入口(可添加权限校验逻辑)
    public List<Banana> GetEditableBananas()
    {
        return _bananas;
    }

    // 自定义包装类:将List<Banana>转换为IReadOnlyList<IBananaRead>
    private class ReadOnlyBananaWrapper : IReadOnlyList<IBananaRead>
    {
        private readonly List<Banana> _source;

        public ReadOnlyBananaWrapper(List<Banana> source)
        {
            _source = source;
        }

        public IBananaRead this[int index] => _source[index];

        public int Count => _source.Count;

        public IEnumerator<IBananaRead> GetEnumerator()
        {
            foreach (var banana in _source)
                yield return banana;
        }

        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    }
}

3. 使用场景示例

  • 只读操作:通过IBoxRead接口访问集合
void ProcessReadOnlyBananas(IBoxRead box)
{
    foreach (var banana in box.Bananas)
        banana.ReadTheBanana();
}
  • 编辑操作:直接访问Box的可编辑列表
void EditBananas(Box box)
{
    foreach (var banana in box.GetEditableBananas())
        banana.EditTheBanana();
}

方案优势

  • 无重复列表,所有操作基于原List<Banana>,避免数据不一致
  • IReadOnlyList<IBananaRead>确保外部无法修改集合结构或调用编辑方法
  • 包装类仅在遍历/访问时映射,无额外内存开销,性能接近原列表

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:23:18