Private Set property not retaining its new value - c#

Working on a problem for a test application I am building, and I can't seem to work out what to do. The app is essentially a questionnaire that is to be passed between two different people using the same device.
However, when I have a private setter for CurrentQuestion, the value never stays modified when being sent across to the new version of the activity. It always retains its original value of 1 (all other values stay modified though). When debugging though, I do see the value of the property increment by 1, it is just not retained.
As soon as I remove the private setter this resolves itself and it increments like normal, but I know this is bad practice, so I would like to find the correct way to do it.
Any help or guidance would be much appreciated, as I feel like I have tried a huge variety of different methods with no luck.

Setting an auto-poroperty like this assumes that all access and modification to that property will be done directly though the property itself, as opposed to using a method like you're doing to increment this property. Based on what you're doing here I would recommend this possible solution to your problem.
Set a backing field for the property and increment that in your NextQuestion method.
private int _currentQuestion;
public int CurrentQuestion => _currentQuestion;
public void NextQuestion()
{
_currentQuestion++;
}

Related

Change object state when using get

Hi I was reading on the microsoft website when I found this, can someone please explain why this is bad programming, because I see it in the way of doing more in less lines of coding. Ps I am still a novice in classes...
It is a bad programming style to change the state of the object by using the get accessor. For example, the following accessor produces the side effect of changing the state of the object every time that the number field is accessed.
private int number;
public int Number
{
get
{
return number++; // Don't do this
}
}
Certainly...
Get is read by most developers as a read only action, and people reading your code will not expect a Get property to be modifying any data. It's a convention, but when you think about it, one that makes sense - it helps us all to understand one another's code.
In the example you cite, one approach would be to make this into two calls - a get, followed by a set to increment the variable... Another would be to implement a method to increment the variable and return the result.
There are perfectly valid reasons to modify the state of an object on get accessors, and that's why it's permitted (for example, for statistical purposes):
For example:
private int _timesMyCustomerWasAccessed;
private Customer _myCustomer;
public Customer MyCustomer
{
get
{
_timesMyCustomerWasAccessed++;
return _myCustomer;
}
}
That said, it's generally bad practice to make state changes on the object that affect how this object is observed from the outside (much worse if the change applies to the results of that very same property).
It's a syntax thing: get accessors are not supposed to have side effects, because they look weird and makes the code hard to understand.
In your example code. Imagine this code accessing the property:
Console.Write(String.Format("{0} {1} {2},
myObject.Number,
myObject.Number,
myObject.Number));
The output would be:
0 1 2
If you try to read that code, except if the object's side effects are perfectly documented, what would make you think that myObject.Number would give different results every time?
For your particular case, it would make much more sense if you had a method:
public int GetNumberAndIncrease()
{
return number++;
}
And when you read that code:
Console.Write(String.Format("{0} {1} {2},
myObject.GetNumberAndIncrease(),
myObject.GetNumberAndIncrease(),
myObject.GetNumberAndIncrease()));
The output is perfectly understandable by just reading that code
As given in your example, lets assume a situation.
You are developing an API in which you are providing the size of the collection(Number) you have restricted to use by the user, but you are allowing the user to see how many contents/items are there in the collection.
Now one has to get the counts at three different places- and in that case you are increasing the number every time he gets it, that is absolutely wrong.
Hope you got the point, why its a bad programming style.

In WPF two-way binding, how can you check if it was a UI element or ViewModel that triggered the binding change?

I'm not sure what keywords to search for...lost in a sea of Google.
I have a two-way databinding specified between a visual element (slider bar) and a numeric value in my ViewModel. I want to differentiate between when a value change is user-initiated vs ViewModel-based, so that I can selectively trigger an event elsewhere in my application. How can I do this in the code-behind of the XAML file?
Update 2015-02-26: In reply to Amit's question, WHY I need this capability is that I actually have more than one visual element set up for 2-way databinding to the same ViewModel source, so not differentiating leads to an infinite loop (stack overflow) in callbacks to dependent code that itself has the ability update the same values.
Aside - shouldn't there be reputation points for the first time one appropriately ues "stack overflow" on SO?
Your best bet is not to have two different behaviors. You need to fire the same notifications and recalculate the same dependent properties either way. But I've run into cases where, say, sometimes I want to fire off an animation and sometimes I don't, so different behaviors can be necessary.
If you really do need two different behaviors, I would just make two different properties (or a property and a method). Bind one property to the UI, and use the other when you're setting the value programmatically. Give each one the side effects it needs to have.
Not only does this keep things simple, it also means you can write unit tests for both sets of behaviors.
I think the short answer is: not really.
When you bind to a ViewModel property from your XAML element, ultimately the WPF binding system will call the property setter in the ViewModel. Once inside the setter method you have no context as to how you got there. You could possibly check the stack to see where you came from but that would be very brittle code and presumably quite slow as well.
If the property was only being set by either the XAML binding or by the ViewModel, then you could set some kind of Boolean flag in your ViewModel like so:
bool _isBeingSetByVM;
public int Number
{
get { return _number; }
set
{
if (_isBeingSetByVM)
{
// ViewModel has set the property
// Do whatever you need to do...
_isBeingSetByVM = false;
}
if (_number != value)
{
_number = value;
OnPropertyChanged("Number"); // generate PropertyChanged event
}
}
}
int _number;
void SomeMethodInVM()
{
_isBeingSetByVM = true;
Number = 42;
}
But again, this is very brittle code that is hard to maintain. As #Amit says in his comment, the better question might be why you need to do this.

What side effects could happen from clearing a list before setting it to a new collection?

I have inherited some code. I see that this code exists:
private List<int> Data { get; set; }
private CsClipboard()
{
Data = new List<int>();
}
public List<int> ComponentIDs
{
get
{
return Data;
}
set
{
Data.Clear();
Data = value;
}
}
I don't see any reason to call clear before setting Data to value. I'm wondering if there are scenarios in C# where I would want to call clear before setting the value aside from something like triggering an OnClear event. It's a fairly large code base with tech. debt, so just being overly cautious.
That code could have some nasty side affects.
What happens there is that the original list gets cleared. so every other place in the code that holds the original list will now hold an empty list.
Every new get request will hold the new list. But the the data isn't concurrent across the program.
In general, you should avoid public properties that return a mutable list. Once a consumer gets a reference to it, you no longer have a guarantee on the state of what should be an internal detail. Clearing the list in a setter only exacerbates the issue, because now you are clearing a list that a consumer might still have a reference to (even though it is no longer the correct list.)
You should consider changing the property so that it returns a copy (preferably read-only) of the current state of the list. The AsReadOnly() method can help here. If you can't do that, at least don't clear the list before setting the new value.
I would want to call clear before setting the value aside from
something like triggering an OnClear event.
The List class does not have events MSDN
So how about writing you own custom Clear method for the list
I mean extension method for the list class that will use your Clear method with your custom logic

How to prevent optimization on a class field in C#

I have built an abstract class that is used to handle command line options for our products.
One need only to create a class inheriting from AbstractOptions, fill it with decorated fields and call the inherited Parse(args) method to have it automatically filled through reflection with values from the command line. Values that were not found on the command line retain their current (default) values.
Then, the application needs only to check the option fields to get their value. The AbstractOptions class provides more features, like help output, etc, but it is beside the point.
Short example:
public class SignalOptions: AbstractOptions
{
[Option("-i, --iterations", "Number of iterations (0 = infinite).")]
volatile public int NumberOfIterations;
[Option("-s, --silent", "Silent mode, only display final results.")]
volatile public bool Silent;
[Option("-w, --zwindow", "Window size for z-score analysis.")]
volatile public int ZWindow = 7;
[Option("-a, --zalert", "z-score value to consider as peak.")]
public double ZAlert = 2.1;
}
static void Main(string[] args)
{
var opts = new SignalOptions();
opts.Parse(args)
// If optimizations are turned off, SILENT will be written or not
// followind presence or absence of the --silent switch on the command line.
// If optimizations are turned on, SILENT will never be written.
// The reflection part is working fine. I suspect the problem is that
// the compiler of the jitter having never found this set anywhere simply inlines
// the value 'false' inthe if, because when I step on it, it shows me the value as
// true or false, but has the same behavior no matter what value opts.Silence has.
if( opts.Silent )
Console.Writeline("SILENT");
}
Now, the problem I have is that since the compiler does not find any code actually changing the values of the SignalOptions class, it simply inlines the values where they are used in the code. I have circumvent the issue by requiring that all 'option' fields in the class be volatile, so no optimization is applied, and it works fine, but unfortunately the volatile keyword is not valid on a double.
I have spent much time on the net trying to find a workaround, without success. Is there anyway to either prevent optimizations on the fields or otherwise fool the compiler/jitter into thinking they are used at runtime?
I also would like to put as less as possible the onus on the calling application.
Thanks
I have a local copy here with Parse written as the rather opaque:
public void Parse(string[] args)
{ // deliberately opaque, not that it would make any difference
string fieldName = (new string('S', 1) + "ilentX").Substring(0, 6);
GetType().GetField(fieldName).SetValue(this, true);
}
It works fine. I do not believe the problem is what you think it is.
Here is my guess:
Parse is running in a separate thread, but as your synchronization is somehow flawed, this makes the rest of code run without having the values set already.
This would also explain why you are seeing the correct values in the debugger.
Update (opinionated):
Having Parse run in a separate thread is very weird, and should be considered a design flaw. Sounds like someone was thinking 'Reflection is slow, let's put it in a separate thread'.

Are .Net property setters ever called implicitly?

I'm on an ASP.Net 2.0 project, in C#. I have some data that gets stored in session state. For ease of use, it is wrapped in a property, like this:
protected IList<Stuff> RelevantSessionData
{
get
{
return (IList<Stuff>) Session["relevant_key"];
}
set
{
Session["relevant_key"] = value;
}
}
Getting and setting the value works exactly as you'd expect. If I want to clear the value, I just set it to null, and there are no problems. However, in another developer's page, he calls the collection's Clear() method. I thought this would be a bug, but it seems to work, and I don't understand why. It works like so:
Debug.WriteLine(RelevantSessionData.Count); //outputs, say, 3
RelevantSessionData.Clear();
Debug.WriteLine(RelevantSessionData.Count); //outputs 0
Why does this work? My naive expectation would be that the middle line loads the serialized value from session, deserializes into an object, calls Clear() on that object, and then lets the unnamed object fall out of scope. That would be a bug, because the value stored in Session would remain unchanged. But apparently, it's smart enough to instead call the property setter and serialize the newly changed collection back into session.
This makes me a little nervous, because there are places in our legacy code where property setters have side effects, and I don't want those getting called if it's not intended.
Does the property setter always get called in a situation like this? Is something else going on? Or do I completely misunderstand what's happening here?
[Added to explain answer]
It turns out did misunderstand. I knew that objects stored in Session must be serializable, and based on that I made too many assumptions about how the collection behaves internally. I was overthinking.
There is only one instance of the stored object (my IList). Each call to the getter returns a reference to that same instance. So the quoted code above works just as it appears, with no special magic required.
And to answer the title question: No, setters are not called implicitly.
Yes, you are right, this would be a bug if your setter/getters were serializing/deserializing the objects. But this is not the case. Instead you are passing based on reference.
So what's basically happening is that the first line in your example gets the item via the get, and Count is called based on that. Then the seccond line is going out and calling get again, returning the same object, running clear, and then the third line is doing the same as the first.
If you had written your setter/getter something like this, you would have a "bug"
protected IList<Stuff> RelevantSessionData
{
get
{
return (IList<Stuff>) JSON.ConvertFromString(Session["relevant_key"]);
}
set
{
Session["relevant_key"] = JSON.ConvertToString(value);
}
}
In this case, a new object would be created and for each call to the get block. But since your example above is simply passing around the reference to the same object, you're not going to see this "bug".
And I say "bug" since it's not really a bug, it's just more of a misunderstanding of what's happening behind the scenes.
I hope this helps.
Your code is roughly equivalent to:
Debug.WriteLine(((IList<Stuff>) Session["relevant_key"]).Count); //outputs, say, 3
((IList<Stuff>) Session["relevant_key"]).Clear();
Debug.WriteLine(((IList<Stuff>) Session["relevant_key"]).Count); //outputs 0
Even if you only call the getter, you are clearing the collection. So the debug output seems normal.
You can expect property setters to be called if:
The are publicly visible (visible to other assemblies).
They implement the setter as part of an interface visible to other assemblies. In some cases, such as
They are used in WPF binding (but the framework will follow the rules about the BindingMode).
They are used in MEF with the ImportAttribute.
They are used in some other binding framework (you get the idea).
You shouldn't run into problems if, for interfaces defined by others, you meet the pre- and post-conditions of the operation.
Edit: I agree with the above. My first choice for exposing a collection is:
private readonly List<T> _sources = new List<T>();
/* Or ICollection<T>, ReadOnlyCollection<T>, or IList<T>, or
* (only a real option for `internal` types) List<T>
*/
public IEnumerable<T> Sources
{
get
{
return _sources;
}
}
If you absolutely must initialize the list after the object is created, then you can use something like this as the second option:
public IList<T> Sources
{
get;
private set;
}
There are situations where the above practices aren't necessarily the best answer, but these are the two most common (IMO?).

Categories

Resources