Basically, I was always in the understanding that you should return the expose base types whenever you can and worry about implementation details internally, which makes sense...
But, I'm not sure what to do here. Basically, right now I have:
ReadOnlyObservableCollection<Foo> MyFoos {get; private set; }
I'm wondering if that should be returned as a ReadOnlyCollection<Foo> or an ICollection<Foo> because internally I never really use any observable parts or attempt to write to the collection. WPF seems to not care what I return, it still binds it and triggers the collection changed notification event properly. But, I read somewhere that I should design this to really have any consuming view handle my ViewModel.
So I'm a bit torn here. I'm thinking that leaving it as a ReadOnlyObservableCollection<T> makes the most sense to explicitly tell the consuming view what they can and can not do with the property, but I'm also under the impression that you should reduce down types to their base types when you can. So I'm not sure what to do here. Especially with the fact that WPF doesn't care what type I return, it figures out that it's observable.
I would probably leave it as ReadOnlyObservableCollection because that very specifically states what a consumer of your ViewModel is allowed to do with your collection. Also note that WPF doesn't actually bind directly to your collection, it binds to the return value of CollectionViewSource.GetDefaultView, which returns an ICollectionView. ICollectionView has INotifyCollectionChanged in its contract.
From a performance perspective, you would want to at least use an items source as a collection that implements INotifyCollectionChanged. MVVM provides a lot of benefits but is primarly concerned with unit testing and separation of concerns, so that choice of whether to use a ReadOnlyObservableCollection or an interface like ICollection{T} would be based on your unit testing goals.
Related
I am starting to learn LINQ-to-SQL for Windows Phone 8, and came across this article on MSDN.
They show a base class for DataContext which implements both INotifyPropertyChanging and INotifyPropertyChanged. The reasoning for the INotifyPropertyChanging is:
◦The INotifyPropertyChanged interface is used for change tracking.
◦The INotifyPropertyChanging interface helps limit memory consumption
related to change tracking.
The article fails to give any specific references to justify the claim of memory consumption to the INotifyPropertyChanging interface. The article on INotifyPropertyChanging itself just says:
Notifies clients that a property value is changing.
Can someone please explain to me how this interface which limits the memory footprint of an application, just by notifying that a property value is about to change (and not even restricting that change to from happening)?
I can only extrapolate, but I think that's what the author had in mind:
In a world without INotifyPropertyChanging, if the consumer needs the old value of a property, it has to preemptively cache it (because, once the PropertyChanged event is raised, it's too late and the value is already changed). Alternatively, the producer can keep a copy of the old value in distinct properties. Either way, the data remains duplicated all the time.
With INotifyPropertyChanging, the consumer doesn't need to cache anything beforehand. When the PropertyChanging event is raised, it can grab the old value, knowing it's about to change. Then the NotifyPropertyChanged event is raised, the consumer can grab the new value, do whatever with both, then drop them. The data is still duplicated, but only at a certain point of time and for a limited duration.
Okay, I finally found another MSDN article which actually explains how INotifyPropertyChanging will limit memory footprint. Quoting the article (emphasis mine):
Notifications are provided through the PropertyChanging event in property setters. When LINQ to SQL is notified of the first change to an object, it creates a copy of the object and considers the object a candidate for generating an Update statement.
For objects that do not implement INotifyPropertyChanging, LINQ to SQL
maintains a copy of the values that objects had when they were first materialized.
So if you don't implement INotifyPropertyChanging and never update any objects fetched using Linq-SQL, it will still create a copy of the object for every object it creates. By implementing the interface, you can avoid that additional memory usage, and have it create copies only when you actually are making a change to the object state.
In the process of adhering to code analysis errors, I'm changing my properties to have private setters. Then I started trying to understand why a bit more. From some research, MS says this:
A writable collection property allows a user to replace the collection with a completely different collection.
And the answer, here, states:
Adding a public setter on a List<T> object is dangerous.
But the reason why it's dangerous is not listed. And that's the part where I'm curious.
If we have this collection:
public List<Foo> Foos { get; set; }
Why make the setter private? Apparently we don't want client code to replace the collection, but if a client can remove every element, and then add whatever they want, what's the point? Is that not the same as replacing the collection entirely? How is value provided by following this code analysis rule?
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...
We have a number of data objects that realize INotifyPropertyChanged to allow for WPF Binding updates. There are also a number of places where our code subscribes to PropertyChanged because we're interested in some value updates.
This results in pretty ugly code where we need to check which property actually changed (we do this using Expressions so it's always type/refactor safe).
Is the preference to raise a specific event (PriceChanged etc...) for when we want to subscribe to it, or hook into PropertyChanged and check the property name?
If a number of properties you want to subscribe to is not very big, I'd create dedicated events as they are better in terms of readability and discoverability.
However, if there are quite a few properties the answer is not so obvious. I usually try to avoid such situations by applying Observer Synchronization pattern (subscribing to Model changes rather than ViewModel). It helps me keep VMs thin.
When databinding my xaml to some data I often use the "get" part of a property to do some logic. Like giving to sum of totals of a list or a check if something is positive.
For example:
public List<SomeClass> ListOfSomeClass{get;set;}
public double SumOfSomeClass
{
get
{
return ListOfSomeClass.Sum(s => s.Totals);
}
}
public bool SumPositive
{
get
{
if(SumOfSomeClass >= 0)
return true;
else
return false;
}
}
This way I can bind to SumPositive and SumOfSomeClass. Is this considered good practice? Even if it gets more complex than this? Or would it be better call a method and return the outcome? What about calls to another class or even a database?
Property getters are expected to be fast and idempotent (i.e. no destructive actions should be performed there). Though it's perfectly fine to iterate over an in-memory collection of objects, I wouldn't recomment doing any kind of heavy lifting in either get or set parts. And speaking of iterating, I'd still cache the result to save a few milliseconds.
Yes, unless it is an operation that might have performance implications. In that case you should use a method instead (as it is more intuitive to the end user that a method might be slow whereas a property will be quick)
I like your naming conventions and I agree entirely with using content such as your example in property getters, if you're delivering an API to be used with binding.
I don't agree with the point others have made about moving code into a method just because it is computationally heavy - that's not a distinction I'd ever make nor have I heard other people suggest that being in a method implies slower than a property.
I do believe that properties should be side-effect-free on the object on which they are called. It's vastly more difficult to guarantee they have no effect on the broader environment - even a relatively trivial property might pull data into memory or at least change the processor cache or vm state.
I say yes, but try to store on a private variable de results of ListOfSomeClass.Sum(s => s.Totals). Specially if you use it more than once.
I don't see any direct issue (unless the list is quite huge) but I would personally use the myInstance.SomeList.Sum() method if possible (.net >= 2.0).
For basic calculations off of fields or other properties in the collection it would be acceptable to do that inside the Get property. As everyone else said true logic should never be done in the getter.
Please change that getter to this:
public bool SumPositive
{
get
{
return SumOfSomeClass >= 0;
}
}
You are already using a boolean expression, no need to explicitly return true or false
Having complex logic in getters/setters is not a good practice. I recommend to move complex logic to separate methods (like GetSumOfXYZ()) and use memoization in property accessors.
You can avoid complex properties by using ObjectDataProvider - it allows you to define method to pull some data.
Depends... if this was on a domain entity then I wouldn't be in favor having complex logic in a getter and especially not a setter. Using a method (to me) signals a consumer of the entity that an operation is being performed while a getter signals a simple retrieval.
Now if this logic was in a ViewModel, then I think the getter aspect is a little more forgivable / expected.
I think that there is some level of logic that is expected in Getters and Setters, otherwise you just have a kind of convoluted way to declare your members public.
I would be careful about putting any logic in the Getter of a property. The more expensive it is to do, the more dangerous it is. Other developers expect a getter to return a value immediately just like getting a value from a member variable. I've seen a lot of instances where a developer uses a property on every iteration of a loop, thinking that they are just getting back a value, while the property is actually doing a lot of work. This can be a major slowdown in your code execution.
It strikes me that Properties in C# should be use when trying to manipulate a field in the class. But when there's complex calculations or database involved, we should use a getter/setter.
Is this correct?
When do you use s/getter over properties?
The .NET design guidelines provide some answers to this question in the Properties vs. Methods section.
Basically, properties have the same semantics as a field. You shouldn't let a property throw exceptions, properties shouldn't have side effects, order shouldn't matter, and properties should return relatively quickly. If any of those things could happen, it's better to use a method. The guidelines also recommend using methods for returning arrays.
When deciding whether to use a property or method, it helps if I think of it like a field. I think about the behavior of the property and ask myself, "If this were a field on the class, would I be surprised if it behaved the way it does?" Consider, for example, the TcpClient.GetStream method. It can throw several exceptions based on if the connection is made, and it's important that the TcpClient is configured before you try to get the stream. Because of this, it is a Get method rather than a property.
If you take a good look at the design guidelines, you'll see that it's usually not a matter of preference; there's good reasons to use methods instead of properties in certain cases.
If your language supports properties, just use properties.
Use the properties. One interesting note from MS's framework design guidelines book is that if you have a property and need to add extra methods for more complex set/get, then you should eliminate the property and go with only get/set methods.
This is all personal preference. When it gets compiled it turns out to be getter/setter functions either way.
I personally use properties when setting and retrieving member values without any side affects. If there are side affects to retrieving/saving the value, then I use a function.
I'd say always ask yourself which makes more sense. Methods tend to be understood as actions to perform and are usually worded as such — open(), flush(), parse(). Properties tend to be understood as fancier fields/variables — DisplayName, AutoSize, DataSource.
This tends to come up a lot with custom control development I've noticed. Since it has the potential of being used by many other people down the road who didn't write it and you might not be around to ask, best go with a design that makes logical sense and doesn't surprise your fellow developers.
I tend to use setters when a value is write-only or there are multiple values to be set at once (obviously). Also my instinct, like yours, is to use getters and setters as a signal that a process may be long-running, spawn threads, or do some other non-trivial work. Also, if a setter has non-obvious prerequisites in the class, I might use a getter or setter instead, since people rarely read documentation on properties, and properties are expected to be accessable at all times. But even in these circumstances I might use a property if it will potentially make the calling code read better.
Forget the Getter and Setter methods. Just use Properties.
An interesting thing to mention is that Properties are ending up as Setter and/or Getter method(s) in the assembly. Setter and/or Getter become a Property just by a little bit of metadata. So in fact, properties = setter/getter methods.
Properties should be fast, as they have a certain promise of just being there. They are also mandatory for databinding.
And they should have no side-effects.
Microsoft's answer is good, but I'd add a few more rules for read-write properties (which Microsoft violates sometimes, btw, causing much confusion): (1) A property setter should generally not affect the observable properties of objects which are not considered to be part of the object whose property is being set; (2) Setting a property to one value and then another should leave any affected objects in the same (observable) state as simply setting it to the second value; (3) Setting a property to the value returned by its getter should have no observable effect; (4) Generally, setting a property should not cause any other read-write properties to change, though it may change other read-only properties (note that most violations of this rule would violate #2 and/or #3, but even when those rules would not be violated such designs still seem dubious). Making an object usable in the designer may require giving it some properties which don't follow these rules, but run-time changes which will not follow such semantics should be done by setter methods.
In many cases, it may be appropriate to have a read-only property and a separate "Set" method (that would be my preference, for example, for a control's "Parent" property). In other cases, it may be useful to have several related ReadOnly properties that are affected by one read/write property (e.g. it may be useful to have a read-only property that indicates whether a control and all its parents are visible, but such functionality should not be included in a read-write Visible property).