Reputation:
public Schedule
{
public Schedule()
{
Payments = new List<Payment>();
}
public List<Payment> Payments
{
get => Payments.Where(x => x.IsActive).ToList();
set { };
}
}
I want to return only Active payments from a collection whenever I get it. Is there a way to make this work? The problem is the code is setting the entire collection and also doing Adds to it throughout the application so I can't just use a private variable and call
set { _payments = value }
In other words, there are places where
Payments = new List<Payment>();
// elsewhere
Payments.Add(payment);
I want to make sure whenever the list is referenced anywhere that only the items in the list that are returned are IsActive
.
Anybody know how to make this work?
Upvotes: 1
Views: 733
Reputation: 37058
If you want Payments
to return a new collection, adding items to that new collection just isn't going to alter the collection your class owns.
This will work.
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.
You might instead want to write a subclass PaymentList : IList<T>
that has an internal List<Payment>
. It would have special behavior for GetEnumerator()
and the indexer, and simply forward everything else to the private collection. That gets to be a lot of work though, when you start thinking about it.
It depends on what you really need here. If the rest of your code needs Schedule.Payments
to return something that can be treated as a List<Payment>
, something will have to change.
Upvotes: 1
Reputation: 7803
You want to provide controlled access to the list, but you are also providing raw access to it.
As you have already figured out, that is not going to work.
I would recommend you hide the details of the implementation by providing methods instead:
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();
}
}
Alternatively, you can create your own collection class and constrain the handling of data within it. Something along these lines:
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();
}
}
Usage:
var list = new PaymentList();
foreach (var item in list)
{
//item would have IsActive = true
}
Upvotes: 2