I have 10 properties where when each is set it increments the value of variable Value. When the value of Value is 10, the app will end. But it seems to be awkward to write the same condition into each of them like this:
int Value=0;
int A
{
set
{
a=value;
Value++;
if(Value>10) ... //check here
}
}
int B
{
set
{
b=value;
Value++;
if(Value>10) //check here again
}
}
How can I simplify checking its value?
You could make a private property for Value and in the setter of that property, if the value is set to above 10, exit the application.
private int value=0;
private int a, b;
public int A
{
set
{
this.a = value;
Value++;
}
get { return this.a; }
}
public int B
{
set
{
this.b = value;
Value++;
}
get { return this.b; }
}
private int Value
{
set
{
this.value = value;
if (this.value > 10)
{
// Exit.
}
}
get { return this.value; }
}
I'm assuming that your properties are in a class which has other responsibilities than exiting the program when the counter hits 10. If so, I would remove the logic of checking the counter and exiting the app from the class.
Maybe you can use an event. The subscriber to this event will be notified when Value hits 10 (you could actually make "10" configurable, but this is just a short example) and exit the app.
class YourClass {
public event ValueHandler ValueIs10;
public EventArgs e = null;
public delegate void ValueHandler(YourClass m, EventArgs e);
private int _value=0;
public int Value {
get {return _value;}
private set {
_value=value;
if(_value==10 && ValueIs10 != null) ValueIs10(this, e);
}
}
public int A
{
set
{
a=value;
Value++;
}
}
public int B
{
set
{
b=value;
Value++;
}
}
// ...
}
private int counter;
private int b;
private int a;
public int A
{
set
{
counter++;
a = value;
CheckCounter();
}
}
public int B {
set
{
counter++;
b = value;
CheckCounter();
}
}
public void CheckCounter()
{
if (counter>10)
{
//Do something
}
}
or make counter a property..
private int Counter
{
set
{
counter = value;
CheckCounter();
}
get
{
return counter;
}
}
and use this when incrementing..
Counter++;
Both answers from #Richard and #Emil are correct, but to make your code more expandable in the future, it's better to implement the built-in INotifyPropertyChanged interface.
class Data : INotifyPropertyChanged
{
private int _counter = 0;
public event PropertyChangedEventHandler PropertyChanged = (sender, arg) =>
{
// if (_counter > 10) Exit();
// from arg you can know what property is changed
// which is probably used for future
};
private int _number;
public int Number
{
get { return _number; }
set
{
//here is another unclear point in your question
//will the counter increases when setting a.Number = 100
//but it's already 100 before setting
if (_number != value)
{
_number = value;
PropertyChanged(this, new PropertyChangedEventArgs("Number"));
}
}
}
}
Related
I have a class for saving interactions in a game, when a person reacts takes values from the status of the game to create a new instance of this class, then send it, this is fine, the problem is when I try to get the value at the end of the level, then every instance of the class has the same value for that property with coincides with the last object declared of that class
public class reactionOrOmission
{
public bool reacted
{
get { return _reacted; }
set { _reacted = value; }
}
public float reactionTime
{
get { return _reactionTime; }
set { _reactionTime = value; }
}
public bool correct
{
get { return _correct; }
set { _correct = value; }
}
public int[] flagType
{
get { return _flagType; }
set { _flagType = value; }
}
public float generalTime
{
get { return _generalTime; }
set { _generalTime = value; }
}
public string focus
{
get
{
return _focus != null ? _focus : "non_focusable";
}
set { _focus = value; }
}
private bool _reacted;
private float _reactionTime;
private bool _correct;
private int[] _flagType;
private float _generalTime;
private string _focus;
public reactionOrOmission(bool Reacted, float ReactionTime, bool Correct, int[] FlagType, float GeneralTime)
{
reacted = Reacted;
reactionTime = ReactionTime;
correct = Correct;
flagType = FlagType;
generalTime = GeneralTime;
if (Tobii.Gaming.TobiiAPI.GetFocusedObject() == null)
{
focus = "non_focusable";
}
else
{
///nonimportant///
}
}
}
Thought it may have been something relating to an integer array but i have tried arrayList and list and the same happens.
I think your class is correct but you use incorrect instances or maybe incorrect usage after create instances...I ran your class and set 4 different instance , each instance has different values.
so your usage of class is incorrect!
I have a class with the property Capacity, when Capacity = 0, object must sets in initial state. I do this with method InitState(), because I can't create a new instance and assignment to this. Is there way use this or another way to set initial state?
public class Test {
private int _field1 = -1;
private int[] _array;
...
public Test() : this(0) { }
public Test(int capacity) {
_array = new int[capacity];
}
...
public int Capacity {
get { return _array.Length; }
set
{
//not working
//if(value == 0) this = new Test();
if(value == 0) InitState();
...
}
}
//sets fields in default state
private void InitState() {
_field1 = -1;
_array = new int[0];
...
}
}
No, you can't assign a value to this so you're code is correct
Can anybody help me with this?:
I'm trying call a method from a my class "numbers" to show that if the entered number is over 50, on button click a message box shows displaying "high" but if it's below 50 it displays "low".
I can't figure out what i'm doing wrong here.
This is the code from my class:
private int number;
private string getNumber(int num)
{
number = num;
return number.ToString();
}
public int numProperty
{
get { return number; }
set { number = value; }
}
public void isHighorlow()
{
if (number >=50)
{
}
else
{
return;
}
}
Note: the int "number" is property that gets it's value from a text box too.
& here is the code from my form:
numbers info = new numbers();
private void Btn_Click(object sender, EventArgs e)
{
info.numProperty = Convert.ToInt32(numberBOX.Text);
info.isHighorlow = Messagebox.Show = ("High");
}
I know that I've not added the "low" bit yet because i'm still trying to see how this works. Sorry if it seems confusing as i'm still learning c#.
I get the error message: cannot assign isHighorlow because it's part of a method group.
And I also realise it's much easier if I just do an if statement on the textbox, but I'm practising Classes and Methods so I'm trying to do it this way.
thanks.
I'm guessing you want something like this:
public string isHighorlow(int number)
{
if (number >=50)
{
return "High";
}
else
{
return "Low";
}
}
numbers info = new numbers();
private void Btn_Click(object sender, EventArgs e)
{
Messagebox.Show(info.isHighorlow(Convert.ToInt32(numberBOX.Text)))
}
IsHighOrLow should be as follows
public bool isHighorlow()
{
if (number >=50)
{
return true;
}
else
{
return false;
}
}
And in button click
if (info.isHighorlow){
//say high
} else
{
// say low
}
isHighorLow is a method, not a property.
MessageBox.Show is a method.
Not sure what you are trying to do but it should be :
if(info.isHigh(Convert.ToInt32(numberBox.Text)))
Messagebox.Show("High");
else
Messagebox.Show("Low");
Meaning you have a method isHigh like so:
public bool isHigh()
{
return number>=50
}
(disclaimer: double check boolean and associated constants per C#)
isHighOrLow doesn't do anything at all. Perhaps this would be better:
public boolean isHigh()
{
if (number >=50)
{
return true;
}
else
{
return false;
}
}
Or, more concisely:
public boolean isHigh()
{
return number >=50;
}
When you call it, this might be closer to what you need:
numbers info = new numbers();
private void Btn_Click(object sender, EventArgs e)
{
info.numProperty = Convert.ToInt32(numberBOX.Text);
if (info.isHigh())
{
Messagebox.Show("High");
}
else
{
Messagebox.Show("Low");
}
}
In your class you have defined void isHighorlow().
This means that you have a method that returns nothing.
Of course such method cannot be used on the left part of an expression like you have done.
Probably you want to write in your class
public bool isHighorlow()
{
if (number >=50)
{
return true;
}
else
{
return false;
}
}
in this way you declare a method that return True if the internal value is >= 50 or false otherwise.
Now, in your form you can use the method in this way
Messagebox.Show(info.isHighorlow() ? "High" : "Low");
However, if the requirement is simply to return a flag for true or false, it is better to use a read only property changing the class code in this way
public bool isHighorlow()
{
get
{
return (number >=50 ? true : false);
}
// No set, read only
}
Try to change your code this way:
private int _number;
private string GetNumber(int number)
{
_number = number;
return number .ToString();
}
public int Number
{
get { return _number; }
set { _number = value; }
}
public string IsHigh()
{
get { if (number >= 50) return true; }
}
numbers info = new numbers();
private void Btn_Click(object sender, EventArgs e)
{
info.Number = Convert.ToInt32(numberBOX.Text);
MessageBox.Show(info.IsHigh ? "High" : "Low");
}
Lets say I have sales price, down payment amount, down payment percent and loan amount. When any of these properties are changed by the user the others need to be updated to reflect the new values. How do you deal with this type of infinite property change events?
When flow control is necessary across multiple attributes, I'll institute a flow control variable - a boolean - and in each property that's being changed, I'll add a test to see if I'm under flow control or not.
private bool controlledChange = false;
public property int MyVal1
{
set
{
_myVal1 = value;
if(!controlledChange)
{
controlledChange = true;
MyVal2 -= 1;
controlledChange = false;
}
}
}
public property int MyVal2
{
set
{
_myVal2 = value;
if(!controlledChange)
{
controlledChange = true;
MyVal1 += 1;
controlledChange = false;
}
}
}
This way whatever property is changed can initiate changes across the other properties, but when they get changed, they will no NOT to initiate their own set of changes in turn.
You should also look to make as many of those properties read only as possible, if they can have calculated results, so that you limit how the object can be changed.
THe easiest way is to only raise a change event if the property has really changed:
public decimal SalePrice {
get{
return salePrice;
}
set {
if (salePrice != value) {
salePrice = value; // putting as first statement prevents the setter
// to be entered again ...
RaiseSalePriceChange();
// Set other properties
}
}
}
I'm not sure I completely understand, since I don't know what you mean by 'infinite'
This may be a good use case for actually backing your properties with fields. That way, you can trigger events on Property sets, but internally set the fields one at a time without triggering N events.
class MyClass
{
private string m_Name;
private int m_SomeValue;
public string Name
{
get { return m_Name; }
set
{
if (value != m_Name)
{
m_Name = value;
m_SomeValue++;
// Raise Event
}
}
}
public int SomeValue
{
get { return m_SomeValue; }
set
{
if (m_SomeValue != value)
{
m_SomeValue = value;
// Raise Event
}
}
}
If INotifyPropertyChanged is really needed to notify external objects, so I would just centralise everything. Like this:
private double salesPrice;
private double downPaymentAmount;
private double downPaymentPercent;
private double loanAmount;
public double SalesPrice
{
get
{
return salesPrice;
}
set
{
if (salesPrice != value)
{
salesPrice = value;
// maybe you would rather use a RecalculateForSalePriceChanged() method
RecalculateDownPaymentAmount();
RecalculateDownPaymentPercent();
RecalculateLoanAmount();
propertiesChanged();
}
}
}
public double DownPaymentAmount
{
get
{
return downPaymentAmount;
}
set
{
if (downPaymentAmount != value)
{
downPaymentAmount = value;
// see above
RecalculateDownPaymentPercent();
RecalculateLoanAmount();
RecalculateSalesPrice();
propertiesChanged();
}
}
}
public double DownPaymentPercent
{
get
{
return downPaymentPercent;
}
set
{
if (downPaymentPercent != value)
{
downPaymentPercent = value;
// see above
RecalculateDownPaymentAmount();
RecalculateLoanAmount();
RecalculateSalesPrice();
propertiesChanged();
}
}
}
public double LoanAmount
{
get
{
return loanAmount;
}
set
{
if (loanAmount != value)
{
loanAmount = value;
// see above
RecalculateDownPaymentAmount();
RecalculateDownPaymentPercent();
RecalculateSalesPrice();
propertiesChanged();
}
}
}
private void propertiesChanged()
{
RaisePropertyChanged("SalesPrice", "DownPaymentAmount", "DownPaymentPercent", "LoanAmount");
}
Maybe you can concentrate the recalculations in less methods or even a single one, but I do not know how you calculate them. But certainly you have to keep a specific order when recalculating the values.
Since they only operate on fields and do not change the properties, there will be no PropertyChanged-feedback-loop.
Hope this helps and I did not misunderstood what you wanted.
What the OP wanted was something like following
class A : INotifyPropertyChanged
{
private int field1;
public int Property1
{
get { return field1; }
set
{
field1 = value;
field2++;
RaisePropertyChanged("Property1");
RaisePropertyChanged("Property2");
}
}
private int field2;
public int Property2
{
get { return field2; }
set
{
field2 = value;
field1++;
RaisePropertyChanged("Property1");
RaisePropertyChanged("Property2");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
What he might be doing was handling other properties in the setter of each property he mentioned thus leading to cyclic invocation of setters.
Vijay
Can I lock/unlock fields or objects at runtime against writing? In other words something like changing objects to read-only temporarily at runtime...
For example:
int x = 5; // x is 5
LockObject(x);
x = 7; // no change
UnlockObject(x);
x = 10; // x is 10
if not can you give me some possible solutions?
You can use accessors to do this...
public class X
{
private bool locked = false;
private int lockedVar;
public int LockedVar
{
get { return lockedVar; }
set { if (!locked) lockedVar = value; }
}
public void LockObject() { locked = true; }
public void UnlockObject() { locked = false; }
}
Wrap it in a property and then use a boolean flag as the "lock".
You can also use a struct to handle this type of logic.
public struct LockableInt
{
private int _value;
public bool Locked;
public void Lock(bool locked) {Locked = locked;}
public int Value
{
get
{ return _value; }
set
{ if (!Locked) _value = value; }
}
public override string ToString()
{
return _value.ToString();
}
}
Sample client code:
public static void RunSnippet()
{
LockableInt li = new LockableInt();
li.Value = 5;
Console.WriteLine(li.ToString());
li.Lock(true);
li.Value = 6;
Console.WriteLine(li.ToString());
li.Lock(false);
li.Value = 7;
Console.WriteLine(li.ToString());
}
Output:
5
5
7
Press any key to continue...
Thanks all for help. Here is a more generalized alternative.
I have decided that it would be more convenient to use freeze/unfreeze since lock/unlock exists in the context of multithreading programming.
public class FreezeableValue<T>
{
private bool frozen;
private T value;
public FreezeableValue()
{
frozen = false;
}
public FreezeableValue(T value)
{
this.value = value;
frozen = false;
}
public void Freeze(bool frozen)
{
this.frozen = frozen;
}
public T Value
{
get { return value; }
set
{
if (!frozen) this.value = value;
}
}
}