Collection properties should be read only - Loophole?

戏子无情 提交于 2019-12-05 15:55:58

Not exposing the setter prevents a situation where the collection is assigned a value of null. There's a difference between null and a collection without any values. Consider:

for (var value in this.myCollection){ // do something

When there are no values (i.e. someone has called Remove on every value), nothing bad happens. When this.myCollection is null, however, a NullReferenceException will be thrown.

Code Analysis is making the assumption that your code doesn't check that myCollection is null before operating on it.

It's probably also an additional safeguard for the thread-safe collection types defined in System.Collections.Concurrent. Imagine some thread trying to replace the entire collection by overwritting it. By getting rid of the public setter, the only option the thread has is to call the thread-safe Add and Remove methods.

If you're exposing an IList (which would be better practice) the consumer could replace the collection with an entirely different class that implements IList, which could have unpredictable effects. You could have subscribed to events on that collection, or on items in that collection that you're now incorrectly responding to.

In addition to SimpleCoder's null checking (which is, of course, important), there's other things you need to consider.

  • Someone could replace the List, causing big problems in thread safety
  • Events to a replaced List won't be sent to subscribers of the old one
  • You're exposing much, much more behavior then you need to. For example, I wouldn't even make the getter public.

To clarify point 3, don't do cust.Orders.clear(), but make a function called clearOrders() instead.

What if a customer isn't allowed to go over a credit limit? You have no control over that if you expose the list. You'd have to check that (and every other piece of business logic) every place where you might add an order. Yikes! That's a lot of potential for bugs. Instead, you can place it all in an addOrder(Order o) function and be right as rain.

For almost every (I'd say every, but sometimes cheating feels good...) business class, every property should be private for get and set, and if feasible make them readonly too. In this way, users of your class get only behaviors. Protect as much of your data as you can!

ReadOnlyCollection and ReadOnlyObservableCollection exists only for read only collection scenearios.

ReadOnlyObservableCollection is very useful for one way binding in WPF/Silverlight/Metro apps.

If you have a Customer class with a List Property then this property should always have a private setter else it can be changed from outside the customer object via:

customer.Orders = new List<Order> 
//this could overwrite data.

Always use the add and remove methods of the collection.

The Orders List should be created inside the Customer constructor via:

Orders = new List<Order>();

Do you really want to check everywhere in your code wether the customer.Orders != null then operate on the Orders?

Or you create the Orders property in your customer object as suggested and never check for customer.Orders == null instead just enumerate the Orders, if its count is zero nothing happens...

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!