Suppose you have a private variable like so
private int _x;
And you have a property that provides external access to this variable:
public int X
{
get
{
return _x;
}
set
{
_x = value;
}
}
Is it better to put "validation" logic (value non-negative, within bounds, etc)
in the getter portion or the setter portion? It seems like it might be acceptable in either, but is there a preferred option?
The setter is preferred, for the following reason: It is better to throw and exception or display a message to the user upon inputting a garbage value, rather than allowing the garbage value, and subjecting your class to internal bad data.
You will note that the MSDN Example uses the setter for input validation.
You want your code to fail as quickly as possible, which is at the point you try to set an invalid value.
When you fail in the setter, the user knows about the problem immediately, and can fix it. If you wait until they try to retrieve the value, you are waiting too late, and the user may have no idea what went wrong, or where.
If the invalid value gets used elsewhere in the code, you are propagating bad data throughout the application, making things much worse, and even less clear to the user what went wrong.
The validation logic should be in the setter, to prevent invalid data from even reaching _x. That way, you have a useful invariant in your class: _x will always contain a valid value.
The idiomatic way to perform validation is to throw an ArgumentException or any of its subclasses when the consuming code tries to assign an invalid value to X.
Validation should be called first. If you want to use this approach you should implement your logic in set clause.
If you want create nice clean code, you should consider dedicated method for it, e.g.:
public class Test
{
public int X { get; private set; }
public void SetX(int value)
{
//... your logic, throw exception if validation failed
X = value;
}
}
Your class should keep your object in valid state.
Related
How will be better in optimization goals?
public SpeedGraphModel SpeedGraphModel
{
get { return _speedGraphModel; }
set {
if (_speedGraphModel == value)
return;
_speedGraphModel = value;
}
}
or
public SpeedGraphModel SpeedGraphModel
{
get { return _speedGraphModel; }
set { _speedGraphModel = value; }
}
I think for string type will be better without checking, but for other types?
Adding another condition check instead of setting the variable value, even if it equal is redundant.
The best case if they are equal you will make 1 operation (condition).
The worst case you will make 2 operations (condition + assignment).
Instead of setting the variable no matter what. => 1 operation.
Such checking is usually used when you call some logic on the setting value (not only just set it). For instance, in desktop (WPF/WinForms) or mobile (Xamarin) you can implement your own property that behavior will be similar to the Dependency Property and call the OnPropertyChanged() method inside it. It can be used for refreshing items of the view after their updating etc. In this way, even if you set the same value to your item and then call OnPropertyChanged() it will update part of the view that can affect the performance, so you would like to make an additional check here.
If you just have a usual property, the only responsibility of which is to set value inside the private field without any logic behind, you don’t need an additional checking as it redundant and won’t increase your performance.
Looking through some code for a built-in Sharepoint webpart, I stumbled upon the following piece of code. What's the practical use of a separate get/set that only modify a different variable when both of them have the same accessibility level? Neither the getter nor the setter execute any additional code either.
private int m_CompatibilityLevel = 14;
private int CompatibilityLevel
{
get
{
return this.m_CompatibilityLevel;
}
set
{
this.m_CompatibilityLevel = value;
}
}
Wouldn't it be easier/more reasonable to use a single variable and give it a value wherever code execution begins? Or is this considered better design?
I have a class PluginProvider that is using a PluginLoader component to load plugins (managed/native) from the file system. Within the PluginProvider class, there is currently defined a property called 'PluginTypes' which calls the 'InitializePlugins' instance method on get().
class PluginProvider
{
IEnumerable<IPluginType> PluginTypes
{
get
{
//isInitialized is set inside InitializePlugins method
if(!isInitialized)
{
InitializePlugins(); //contains thread safe code
}
//_pluginTypes is set within InitializePlugins method
return _pluginTypes;
}
}
}
I am looking at refactoring this piece of code. I want to know whether this kind of initialization is fine to do within a property. I know that heavy operations must not be done in a property. But when i checked this link : http://msdn.microsoft.com/en-us/library/vstudio/ms229054.aspx , found this " In particular, operations that access the network or the file system (other than once for initialization) should most likely be methods, not properties.". Now I am a bit confused. Please help.
If you want to delay the initialization as much as you can and you don't know when your property (or properties) will be called, what you're doing is fine.
If you want to delay and you have control over when your property will be called the first time, then you might want to make your method InitializePlugins() public and call it explicitly before accessing the property. This option also opens up the possibility of initializing asynchronously. For example, you could have an InitializePluginsAsync()that returns a Task.
If delaying the initialization is not a big concern, then just perform the initialization within the constructor.
This is of course a matter of taste. But what i would do depends on the length of the operation you're trying to perform. If it takes time to load the plugins, i would create a public method which any user would need to call before working with the class. A different approach would be to put the method inside the constructor, but IMO constructors should return as quickly as possible and should contain field / property initialization.
class PluginProvider
{
private bool _isInitialized;
IEnumerable<IPluginType> PluginTypes { get; set;}
public void Initialize()
{
if (_isInitialized)
{
return;
}
InitializePlugins();
_isInitialized = true;
}
}
Note the down side of this is that you will have to make sure the Initialize method was called before consuimg any operation.
Another thing that just came to mind backing this approach is exception handling. Im sure you wouldn't want your constructorcto be throwing any kind of IOException in case it couldn't load the types from the file system.
Any initialization type of code should be done in the constructor, that way you know it will be called once and only once.
public class PluginProvider
{
IEnumerable<IPluginType> PluginTypes
{
get
{
return _pluginTypes;
}
}
public PluginProvider()
{
InitializePlugins();
}
}
What you are doing there is called lazy initialization. You are postponing doing a potentially costly operation until the very moment its output is needed.
Now, this is not an absolute rule. If your InitializePlugins method takes a long time to complete and it might impact user experience, then you can consider moving it into a public method or even making it asynchronous and call it outside of the property: at app startup or whenever you find a good moment to call a long-lasting operation.
Otherwise, if it's a short lived one-time thing it can stay there. As I said, not an absolute rule. Generally these are some guidelines for whatever applies to a particular case.
In existing code of my project, at number of places the property is declared like this:
public long ResourceID
{
get
{
return this.resourceID;
}
set
{
if (this.resourceID != value)
{
this.resourceID = value;
}
}
}
Note: private long resourceID is already declared.
Properties not only of value types but also of reference types (including string) too are declared like this.
Another example:
public Collection<Ability> Abilities
{
get
{
return this.abilities;
}
set
{
if (value == null)
{
throw new ArgumentNullException("Abilities");
}
this.abilities = value;
}
}
As per my knowledge, the setter in the first example does not make any sense and the if condition is meaningless there. So i decided to change the code (as part of refactoring) to make them Auto-Properties. (In second example I need setter since exception is handled there.)
I want to know from experts here, will whether making existing properties auto properties (or at least removing if condition from setter) cause any harm? Sometimes there are subtle things which a developer may not be aware of and some changes can have side effects too. That's why I am asking this question. (My libraries are used at many places.)
Note: Let me know if this is purely a homework question.
Converting:
private long resourceID;
public long ResourceID
{
get
{
return this.resourceID;
}
set
{
this.resourceID = value;
}
}
into:
public long ResourceID { get; set; }
won't cause any harm, guaranteed.
Removing the if statement might cause harm. For example in WPF when working with the MVVM pattern and implementing the INotifyPropertyChanged interface it is often good practice to check whether the value has changed before actually setting it. Removing this check will provoke notifications to be sent to the UI no matter whether the value changed or not. So it would be a breaking change.
I can only think of one kind of problem you could run into (which is fixable):
If you are using ORM or other external tool, they might rely on a naming convention for finding properties/fields. So, the 3rd party dll might be looking for a field resourceId that no longer exists.
So, code using reflection to access fields might break, but if you have control over the codebase, that is unlikely to be an issue.
There are some edge-cases where this might cause harm:
Changing to an automatically implemented property {get;set;}
if you are using field-based serialization at any point (for example, BinaryFormatter), then this will break when changing to an automatically implemented property, as the field-name will change. This will also impact any other scenario that uses reflection to access the (hopefully private) fields, but BinaryFormatter is the most common cause of confusion here.
Removing the if test
will be fine for most data-types such as long etc, however, if you use it with a type that implements a custom equality operation, you might find you are suddenly swapping a reference when previously (with the if) the objects reported equal for different references
The first is a more likely problem. If you are using BinaryFormatter, then keep the private field (byt maybe remove the if test). And then start refactoring your code away from BinaryFormatter ;p
What you have done is correct. The if statement is meaningless. I always think that less code is better, because the lines of code is directly proportional to the number of faults.
public long ResourceID { get; set; }
Your first example only sets the resourceID field if its value has changed.
The only difference you would see by removing the "if" test is a possible impact if multiple threads are reading the value. In which case they probably should be using a lock, so it's almost certainly safe to remove the test.
Your second example prevents a caller from setting the property value to null. Presumably the field is initialized to a non-null value, and this has value as it means that callers can read the property without needing to check for null.
Usually in such scenarios and how you've explained, it shouldn't be a concern.
You could just go ahead and change the code of all properties;
public long ResourceID { get; set; }
Or
public long ResourceID
{
get { return this.resourceID; }
set { this.resourceID = value; }
}
But it might cause an issue if upon
changing the value of the property,
it cascades to some other custom
function-call which is only executed
if the new value is different from
old ones. Usually when when you've implemented custom events or even maybe in case of property-changed events
Also might affect, when using
Data-Context classes
Both scenarios are totally application specific.
I'd suggest you reactor with caution. Or as you've written yourself, HOMEWORK.
I'm working in .net 3.5.
I have a class "A" which has a stack and a getter property which, when called, removes the first item in the stack and retrieves the next one.
After initializing the class, I saw that the getter works without being called, and removes the top item in the stack, thus giving me bad results. A breakpoint in the getter did not show anyone passing through it.
When I change the property to a function, the stack is returned ok.
I'd be happy if someone could explain why is that.
Here is the simplified class:
public class A
{
private Stack<string> Urls;
public A(string title, string[] array)
{
Urls = new Stack<string>();
foreach (string s in array)
{
Urls.Push(s);
}
}
public string Url
{
get { return Urls.Peek(); }
}
public string NextUrl
{
get{
if (Urls.Count > 1)
{ Urls.Pop(); }
return Urls.Peek();
};
}
}
Firstly, making a property accessor change the state is generally a bad idea. The most it should do is lazily initialize something - or possibly give a volatile value (like DateTime.Now does).
Secondly, you're probably seeing this if you're running under the debugger - it accesses properties while you're stepping through code. That would probably explain why the breakpoint wasn't being hit, too.
Urls.Pop();
wants to be
return Urls.Pop();
as it returns the value and removes it from the list at the same time
Actually having re-read your question, it looks like it is because the debugger evaluates properties. If you run the application without the debugger do you get the same problem?
This is bad design I think. A get accessor should not mutate the object in a way that causes different results on subsequent calls.
IMO, the problem here is having a property that has non-obvious side-effects; this should be a method:
public string GetNextUrl() { /* */ }
Otherwise bad things happen everywhere (the debugger, data-binding, etc). Don't assume that somebody only reads a property once.
The only sensible use of side-effects in properties is things like lazy-loading, deferred initialization, etc. It should still report the same value when called sequentially without any other obvious mutating calls.