What I am doing wrong with below "Set" property? - c#

I was trying to create simple event and below is the block of code but its not working. When I try to debug, as soon as we create Point object it is throwing "StackOverFlowException" at "Set" property(even before we assign the value p.x=10). What I am doing wrong?
using System;
namespace Workshop
{
public class Point
{
public int x
{
get { return x; }
set
{
x = value;
onPointeChanged();
}
}
public int y
{
get { return y; }
set
{
y = value;
onPointeChanged();
}
}
public event EventHandler pointchanged;
private void onPointeChanged()
{
if (pointchanged != null)
pointchanged(this, EventArgs.Empty);
}
}
public class Program
{
public static void Main(String[] args)
{
Point p = new Point();
p.pointchanged += HandleEvent;
p.x = 10;
}
public static void HandleEvent(object obj, EventArgs sender)
{
Console.WriteLine("Event Raised");
}
}
}
Thanks

You are calling the set method indefinitelly until you run out of stack memory. What you're doing with
x = value;
is you're calling the x property's setter, which in turn does x = value, so it calls itself, and so on, and so on for all eternity.
To fix this, introduce a field:
private int x;
public int X
{
get => x;
set
{
x = value;
OnPointChanged();
}
}
This is the proper way of creating properties with custom logic behind get and/or set. If you didn't have your OnPointChanged() logic you could just do
public int X { get; set; }
which would generate the following code for you under the hood:
private int x;
public int X { get => x; set => x = value; }

The problem is you are assigning the property a value in its own setter:
public int x
{
get { return x; }
set
{
x = value; // <-- see you are assigning `value` to your `x` property.
onPointeChanged();
}
}
This will loop over and over again ad infinitum. You need to create a backing field:
private int _myField;
public int BetterNameThanX
{
get { return _myField; }
set
{
_myField = value;
onPointeChanged();
}
}

You have defined properties and you return every own property which causes recursivity on get and set scopes. Try to define private attributes and expose it by properties:
public class Point
{
private int _x;
public int x
{
get { return _x; }
set
{
_x = value;
onPointeChanged();
}
}
private int _y;
public int y
{
get { return _y; }
set
{
_y = value;
onPointeChanged();
}
}
public event EventHandler pointchanged;
private void onPointeChanged()
{
if (pointchanged != null)
pointchanged(this, EventArgs.Empty);
}
}

Related

Raise event whenever function returns true without update loop

Right now I do not have an update loop in my program and I would like to avoid having one for future flexibility, but I am not sure if this is possible without one.
If I have a Boolean value like: bool Update => a == b && c != d , is it possible to have a function get called automatically when that is true.
Alternatively, I know I can do something like this:
CheckUpdate()
{
if(Update)
*do something here*
}
But I'd like the message to be sent the moment value is true, not when the update loop detects that it is true.
I would have a State class that you then attach your events to using INotifyPropertyChanged.
public class State: INotifyPropertyChanged
{
private string a;
private string b;
private string c;
private string d;
public event PropertyChangedEventHandler PropertyChanged;
// This method is called by the Set accessor of each property.
// The CallerMemberName attribute that is applied to the optional propertyName
// parameter causes the property name of the caller to be substituted as an argument.
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public string A
{
get { return this.a; }
set
{
if (value != this.a)
{
this.a= value;
NotifyPropertyChanged();
}
}
}
... so on and so forth ...
}
Now all you have to do is assign a handler to the property change...
var myState = new State();
myState += (sender,args) =>
{
if( myState.A == myState.B && myState.C != myState.D)
{
// do stuff
}
};
The reason I use the interface is so the object can be used in an ObservableCollection too if needed. This way you can manage multiple states at the same time.
Try something like this:
public class Foo
{
public Foo()
{
_update = () => a == b && c != d;
}
private Func<bool> _update;
private string a;
private string b;
private string c;
private string d;
private string e;
private string f;
private string g;
private string h;
private void CheckUpdate()
{
if (_update())
{
/*do something here*/
}
}
public string A { get { return a; } set { a = value; CheckUpdate(); } }
public string B { get { return b; } set { b = value; CheckUpdate(); } }
public string C { get { return c; } set { c = value; CheckUpdate(); } }
public string D { get { return d; } set { d = value; CheckUpdate(); } }
public string E { get { return e; } set { e = value; CheckUpdate(); } }
public string F { get { return f; } set { f = value; CheckUpdate(); } }
public string G { get { return g; } set { g = value; CheckUpdate(); } }
public string H { get { return h; } set { h = value; CheckUpdate(); } }
}
It doesn't matter how many properties you have you just call CheckUpdate() on every update. You can then change _update at any time, compile-time or run-time, to suit your requirements.

C# - Getter and Setter dosen't keep the value

Here is my code:
private int pressedMain = 1;
public int PressedMain
{
get
{
return pressedMain;
}
set
{
pressedMain = value;
}
}
And then I change the value of pressedMain:
pw.PressedMain++;
But in the following class my value is one, why and how can I slove this problem?
Example invoke, console prints 2 here
public class Foo
{
private int pressedMain = 1;
public int PressedMain
{
get
{
return pressedMain;
}
set
{
pressedMain = value;
}
}
}
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo();
foo.PressedMain++;
Console.WriteLine(foo.PressedMain);
Debugger.Break();
}
}

How to set a read only property with a set accessor

I have created a class that has an automatic property for an int variable called BagsOfFeed. I added an automatic property to prevent the value from being changed from outside the class.
I use another property that calculates the BagsOfFeed only when the NumberOfCows property is set.
I have come across problem when I make BagsOfFeed readonly it prevents the NumberOfCows property from assigning a value to BagsOfFeed.
here is the class Code
namespace cow_calculator1
{
class Farmer
{
public Farmer(int numberOfCows, int feedMultiplier)
{
this.feedMultiplier = feedMultiplier;
NumberOfCows = numberOfCows;
}
public int BagsOfFeed { get { return BagsOfFeed; } }
private int feedMultiplier;
public int FeedMultiplier
{
get
{
return feedMultiplier;
}
}
private int numberOfCows;
public int NumberOfCows
{
get
{
return numberOfCows;
}
set
{
numberOfCows = value;
BagsOfFeed = numberOfCows * FeedMultiplier;
}
}
}
}
this is the form Code
namespace cow_calculator1
{
public partial class Form1 : Form
{
Farmer farmer;
public Form1()
{
InitializeComponent();
farmer = new Farmer(15, 30);
}
private void calculate_Click(object sender, EventArgs e)
{
Console.WriteLine("I need {0} bags of feed for {1} cows", farmer.BagsOfFeed, farmer.NumberOfCows);
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
farmer.NumberOfCows = (int) numericUpDown1.Value;
}
}
}
this is the error
Error 1 Property or indexer 'cow_calculator1.Farmer.BagsOfFeed' cannot be assigned to -- it is read only ( "Line 38" "Column 17" cow calculator1)
You can scope a setter to be private, and remove the return value.
public int BagsOfFeed { get; private set; }
Which is roughly equivalent to
private int bagsOfFeed;
public int BagsOfFeed {
get { return bagsOfFeed; }
private set { bagsOfFeed = value; }
}
Or in the second format you could just set the private backing store directly.

'does not implement interface member 'System.ICloneable.Clone()'

I'm having a small issue calling in the Icloneable interface
I've told the class I want to use the interface as such:
class UnitClass: ICloneable
and have placed in a function for Cloning
public Object Clone()
{
return this.MemberwiseClone();
}
however for some reason the program is telling me that I have not implemented System.ICloneable.clone() I even tried giving the function the explicit name like so...
public Object System.ICloneable.Clone()
but with little effect, anybody know what I'm doing wrong?
edit: Full class
class UnitClass: ICloneable
{
//-----------------------------------------------------------------------------------------------
//----------------------------------------------Variables----------------------------------------
private int unitID; //added for xml
private string unitName;
private int unitBaseHP;
private int unitCurrentHP;
private Carrier unitCarrier;
private int unitRechargeTime;
private int turnLastPlayed;
private int strengthAgainstFighters;
private int strengthAgainstBombers;
private int strengthAgainstTurrets;
private int strengthAgainstCarriers;
//-----------------------------------------------------------------------------------------------
//---------------------------------------------Constructor---------------------------------------
public UnitClass()
{
unitID = 0;
unitName = "Name Not Set";
unitBaseHP = 0;
unitCurrentHP = 0;
unitCarrier = null;//Carrier works as faction ie red/blue or left/right
unitRechargeTime = 0;
turnLastPlayed = 0;
strengthAgainstFighters = 0;
strengthAgainstBombers = 0;
strengthAgainstTurrets = 0;
strengthAgainstCarriers = 0;
}
//-----------------------------------------------------------------------------------------------
//---------------------------------------------Gets and Sets-------------------------------------
public int UnitID//public
{
set { unitID = value; }
get { return unitID; }
}
public string UnitName//public
{
set { unitName = value; }
get { return unitName; }
}
public int UnitBaseHP//public
{
set { unitBaseHP = value; }
get { return unitBaseHP; }
}
public int UnitCurrentHP//public
{
set { unitCurrentHP = value; }
get { return unitCurrentHP; }
}
public Carrier UnitCarrier//public
{
set { unitCarrier = value; }
get { return unitCarrier; }
}
public int UnitRechargeTime//public
{
set { unitRechargeTime = value; }
get { return unitRechargeTime; }
}
public int TurnLastPlayed//public
{
set { turnLastPlayed = value; }
get { return turnLastPlayed; }
}
public int StrengthAgainstFighters//public
{
set { strengthAgainstFighters = value; }
get { return strengthAgainstFighters; }
}
public int StrengthAgainstBombers//public
{
set { strengthAgainstBombers = value; }
get { return strengthAgainstBombers; }
}
public int StrengthAgainstTurrets//public
{
set { strengthAgainstTurrets = value; }
get { return strengthAgainstTurrets; }
}
public int StrengthAgainstCarriers//public
{
set { strengthAgainstCarriers = value; }
get { return strengthAgainstCarriers; }
}
//---------------------------------------------------------------------------
public object Clone()
{
return this.MemberwiseClone();
}
}
This built fine for me.
public class MyClone : ICloneable
{
public object Clone()
{
return this.MemberwiseClone();
}
}
You don't perhaps want to share any more of your class? Nothing is really jumping out at me.

What is the proper way to handle an array of one class in another class?

Here are two simple classes to illustrate my question:
class Widget
{
private int _widgetID;
public int WidgetID
{
get { return _widgetID; }
set { _widgetID = value; }
}
private int _categoryID;
public int CategoryID
{
get { return _categoryID; }
set { _categoryID = value; }
}
private string _widgetName;
public string WidgetName
{
get { return _widgetName; }
set { _widgetName = value; }
}
}
And them the second class:
class WidgetCategory
{
private int _widgetCategoryID;
public int WidgetCategoryID
{
get { return _widgetCategoryID; }
set { _widgetCategoryID = value; }
}
private Widget[] _widgets;
public Widget[] Widgets
{
get { return _widgets; }
set { _widgets = value; }
}
private string _widgetCategoryName;
public string WidgetCategoryName
{
get { return _widgetCategoryName; }
set { _widgetCategoryName = value; }
}
}
How would I handle this situation in the most efficient way?
Also, so you know, I will need to nest other classes the same way below the Widget class.
You should create a read-only property of type System.Collections.ObjectModel.Collection<Widget>.
Collection properties should be read only
Use Collection<T>

Categories

Resources