在 collection 上过滤 getter

Filter in getter on a collection

public Schedule 
{
    public Schedule()   
    {    
        Payments = new List<Payment>();
    }

    public List<Payment> Payments 
    {
        get => Payments.Where(x => x.IsActive).ToList();
        set { };
    }
}

我只想 return 收到 collection 的主动付款。有没有办法使这项工作?问题是代码设置整个 collection 并在整个应用程序中对其进行添加,所以我不能只使用私有变量并调用

set { _payments = value }

换句话说,有些地方

Payments = new List<Payment>();
// elsewhere
Payments.Add(payment);

我想确保每当在任何地方引用列表时,只有列表中 returned 的项目是 IsActive

有人知道怎么做吗?

如果您想要 Payments 到 return 一个新的 collection,向新的 collection 添加项目不会改变 collection您的 class 拥有。

这会奏效。

private List<Payment> _payments = new List<Payment>;

public IEnumerable<Payment> Payments => _payments.Where(x => x.IsActive);

public void AddPayment(Payment pmt) => _payments.Add(pmt);  

//  You can write ClearPayments(), RemovePayment(), etc.

您可能想要编写一个具有内部 List<Payment> 的子 class PaymentList : IList<T>。它会对 GetEnumerator() 和索引器有特殊的行为,并简单地将其他所有内容转发给私有 collection。但是,当您开始考虑它时,这将是很多工作。

这取决于您在这里真正需要什么。如果您的代码的其余部分 需要 Schedule.Payments 到 return 可以被视为 List<Payment> 的东西,则必须进行一些更改。

您想提供对列表的受控 访问,但您也提供对列表的原始 访问。

如您所知,这是行不通的。

我建议您通过提供方法来隐藏实现的细节:

public Schedule 
{
    private List<Payment> _payments;
    public Schedule() 
    {
        _payments = new List<Payment>();
    }

    public IEnumerable<Payment> GetActivePayments()
    {
        //Do whatever you want here, e.g....
        return _payments.Where(x => x.IsActive).ToList();
    }

    public void AddPayment(Payment payment)
    {
        //Do whatever you want here, e.g....
        _payments.Add(payment);
    }

    public void ClearPayments()
    {
        //Do whatever you want here, e.g....
        _payments.Clear();
    }
}

或者,您可以创建自己的集合 class 并限制其中的数据处理。沿着这些线的东西:

public class PaymentList : IEnumerable<Payment>
{
    private List<Payment> _payments = new List<Payment>();

    public IEnumerator<Payment> GetEnumerator()
    {
        return _payments.Where(p => p.IsActive).GetEnumerator();
    }

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

用法:

var list = new PaymentList();
foreach (var item in list)
{
    //item would have IsActive = true
}