How to tie one variable to another - c#

I have this bit of code:
Brick brick1= new Brick(parent.X - 1,parent.Y);
X & Y are integers,
Basiclly what i want to do is: when the x of the parent brick changes, the x of brick1 changes,where it dosnt matter the value of parent.X, brick1.X will always be equal to parent.X - 1
Is there an way of accomplishing this?

Assuming that Brick is not a struct you could do this. You could also do this through inheritance with a ChildBrick class but unless you need the added complication, at least in my mind, it is simpler to just allow Brick to have a parent that is a Brick and add a constructor for the parent. Then if you retrieve a value and it needs to be computed from the parent you just check for whether you have a parent and calculate accordingly.
class Brick
{
private Brick _parent;
private int _x;
private int _y;
Brick(Brick parent) {_parent = parent);}
Brick(int x, int y)
{
_x = x;
_y=y;
}
public int X
{
get
{
if (_parent != null) return _parent.X - 1;
return _x;
}
}
public int Y
{
get
{
if (_parent != null) return _parent.Y;
return _y;
}
}
}

Just make brick1 a derived class with a calculated read only property
public class childBrick: Brick
{
public new float X
{
get { return base.X - 1.0 }
private set { base.X = value; }
}
public static Brick Make( float x, float y)
{
return new childBrick
{
X = x;
Y = y;
}
}
}
use it like this
Brick brick1 = childBrick.Make(parent.X - 1,parent.Y);

Related

How to fix Console Writing the name of the Class? [duplicate]

This question already has answers here:
Class List Keeps Printing Out As Class Name In Console?
(4 answers)
Closed 3 years ago.
I am new to C# and I am struggling with this since hours and would appreciate your help.
I want to create a Polygon and Write down each position of the points.
Currently I have this:
-Class Point
class Point
{
private int x;
private int y;
public Point(int x2, int y2)
{
x = x2;
y = y2;
}
}
-Class Polygon
class Polygon
{
private Point[] Points;
public Polygon(params Point[] a)
{
Points = new Point[a.Length];
for (int i = 0; i < a.Length; i++)
{
Points[i] = a[i];
}
}
public Point this[int index]
{
get { return Points[index]; }
set { Points[index] = value;}
}
}
Now I have this in my main:
Polygon First= new Polygon(new Point(7,4), new Point(4,1), new Point(2, 1));
First[0] = new Point(3, 4);
Console.WriteLine("points of polygon ");
for (int i = 0; i < First.PointCounter; i++)
{
Console.WriteLine(First[i]);
}
But now instead of seeing each position of the Point after "points of polygon" I see this in my Console: https://imgur.com/Z5aVFMK
How it should look like: https://imgur.com/a/aFkdrEF
How it should look like: https://imgur.com/a/aFkdrEF
I added an override of ToString so that your Point class has the expected output when converted to string. An output like "x:3 y:4".
class Point
{
public int x { get; private set; }
public int y { get; private set; }
public Point(int x2, int y2)
{
x = x2;
y = y2;
}
public override string ToString()
{
return $"x:{x,-3} y:{y,-3}";
}
}
As it is now, it is a good candidate for becoming a struct instead of class.
C# is not "interpreted" like other languages, so the Console.WriteLine method won't guess what you're trying to have printed.
To give the result you're looking for, with your current code, you would have to provide public properties to your Point class:
public int X { get { return x;} set{ x = value;} }
public int Y { get { return y;} set{ y = value;} }
After which you could now access those properties in your for loop:
for (int i = 0; i < First.PointCounter; i++)
{
Console.WriteLine($"x:{First[i].X} y:{First[i].Y}");
}

Trigger "Set" when changed class object property C#

If I have a custom class Vector3 and I have a class object Myobject that use the vector3 class as a property and when I set a new vector
myobject.pos = new vector3(x,y,z); the set will trigger in this case Debug.Log("set") as expected but If I instead of creating a new vector I only want to change x but still have set triggered I would want to do myobject.pos.x = x but this will not trigger the set in MyObject but the set in my vector3 class for x is there any way of fixing this so set in MyObject triggers when I change only the "sub property" x of the vector3.
public class MyObject{
private Vector3 p_pos = new Vector3(0, 0, 0);
public Vector3 pos
{
get { return (p_pos); }
set
{
Debug.Log("set");
p_pos = value;
}
}
}
The only way I can think of doing it is to create a separate method in MyObject class like this MyObject.SetPosX(x):
public void SetPosX(double _x)
{
Debug.Log("set");
p_pos.x = _x;
}
But It is not a very clean way of doing it so would prefer another solution.
The way I see it could be implemented in a more structured way is to allow Vector3 notify someone when a property has been changed. My object class would be listening to and react when necessary.
In the code you provide it looks like overhead but in fact, it depends on a real situation.
Code is below
using System;
using System.Diagnostics;
public class Program
{
public static void Main()
{
MyObject myObject = new MyObject();
Vector3 vector3 = new Vector3(1, 1, 1);
myObject.p_pos = vector3;
myObject.p_pos.X = 5;
Console.ReadLine();
}
}
public class Vector3
{
public Vector3(double x, double y, double z)
{
X = x; Y = y; Z = z;
}
private double _x;
private double _y;
private double _z;
public double X
{
get
{
return _x;
}
set
{
_x = value;
OnPropertyChanged(EventArgs.Empty);
}
}
public double Y
{
get
{
return _y;
}
set
{
_y = value;
OnPropertyChanged(EventArgs.Empty);
}
}
public double Z
{
get
{
return _z;
}
set
{
_z = value;
OnPropertyChanged(EventArgs.Empty);
}
}
public event EventHandler PropertyChanged;
protected virtual void OnPropertyChanged(EventArgs e)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, e);
}
}
}
public class MyObject
{
private Vector3 _p_pos = null;
public Vector3 p_pos { get
{
return _p_pos;
}
set
{
if (_p_pos != null)
_p_pos.PropertyChanged-= _p_pos_PropertyChanged;
_p_pos = value;
_p_pos.PropertyChanged += _p_pos_PropertyChanged;
}
}
private void _p_pos_PropertyChanged(object sender, EventArgs e)
{
Console.Write("_p_pos_PropertyChanged");
}
}
The other way which could be more preferable is to make vector3 immutable so each time you need to change the value you have to create the new instance of vector3. This should allow you to stay with the lightweight version of vector3 and still have control over its value.
As the reason why it works like that seems not to be answered, I'll give it a shot.
public class TestClass
{
private Vector3 _v = 0;
public Vector3 V { get { return _v; } set { _v = value; } }
void DoSomething ()
{
V = new Vector3 (2, 0, 0); // This will trigger 'set'.
V.x = 2; // This will not.
}
}
If you have a Vector3 property and set its specific values, you set the values within the Vector3 class itself, but do not affect the assignment/reference to the said Vector3. In order to change its x value, you do not set a new or other Vector3 for 'V'. One way to circumvent that, as you already figured out, is simply to use a method to change the values of 'V' and trigger your extra code. Another one would be to have your own class which triggers your extra code when its properties are changed (for Vector3 not quite possible).
If you only want to track changes to Vector3s, you'd have to create something like a value Watcher class, which would be triggered in update to detect changes to values you want to track. To create this could be quite sophisticated and would involve lambda expressions and generics at least, possibly even an entire code structure in Unity by using a global base class for everything that shall inherit from MonoBehavior.

struct in C# doesn't work as expected

I'm working on a simple application and I'm a little confused. I have a simple struct Point with int x and int y. And I use it for Line
public class Line : Shape {
public Line() {
PointA = new Point(x: 0, y: 0);
PointB = new Point(x: 0, y: 0);
}
public Point PointA { get; set; }
public Point PointB { get; set; }
}
and somewhere
var line = new Line();
line.PointB = new Point(x: 4, y: 2);
Console.WriteLine($"Line start at {line.PointA.GetX()}:{line.PointA.GetY()}; end at {line.PointB.GetX()}:{line.PointB.GetY()}");
for (int i = 0; i < 10; i++) {
line.PointB.IncrementX();
line.PointB.IncrementY();
}
Console.WriteLine($"Line start at {line.PointA.GetX()}:{line.PointA.GetY()}; end at {line.PointB.GetX()}:{line.PointB.GetY()}");
Here need to increment x and y of Point but result doesn't change:
Line start at 0:0; end at 4:2
Line start at 0:0; end at 4:2
What I'm doing wrong? It seems strange. Are there some specific rules to use struct in C#. I know that this is a value type but I think it is a good for Point. All examples uses struct for Point. Please help?
Point:
public struct Point {
private int _x;
private int _y;
public Point(int x, int y)
: this() {
_x = x;
_y = y;
}
public void IncrementX() {
_x++;
}
public void IncrementY() {
_y++;
}
public int GetX() {
return _x;
}
public int GetY() {
return _y;
}
}
Struct is a value type. And it is passed by value (i.e. by creating copy of all fields) instead of passing reference to struct instance. So when you do
line.PointB.IncrementX()
When you call getter of PropertyB, it returns copy of Point which is stored at PropertyB backing field. And then you call increment on copy. Thus original value will stay unchanged.
Further reading: Value and Reference Types and especially Mutating Readonly Structs which says
mutable value types are evil. Try to always make value types
immutable.
What you can do if you want to actually move line point?
Change Point type to class. Then it will be passed by reference, and all methods will be called on original point which you store in Line.
Assign new (modified) point instance to line
I.e. you should store copy, change it and assign back
var point = line.PointB; // get copy
point.IncrementX(); // mutate copy
point.IncrementY();
line.PointB = point; // assign copy of copy
You can also make your Point struct immutable (the best thing you can do for value types):
public struct Point
{
public Point(int x, int y)
{
X = x;
Y = y;
}
public int X { get; }
public int Y { get; }
public Point IncrementX() => new Point(X + 1, Y);
public Point IncrementY() => new Point(X, Y + 1);
public Point Move(int dx, int dy) => new Point(X + dx, Y + dy);
}
And now changing location will look like
line.PointB = line.PointB.Move(1, 1);

Get/Set The Members of a Struct or a Class in a Class C#

If I have a Struct or a Class, lets say I'm using a Vector2 (which has two members, float X and float Y), how am I supposed to properly get/set its methods in a class?
This is the code I know of right now:
public class MyClass
{
private Vector2 vector; //Has to be private
public Vector2 Vector
{
get { return vector; }
set { vector = value; }
}
}
But what if I wanted to edit the members (or certain members) of the Vector2 with the set method? Something like this is what I'm asking for:
set.X
{
vector.X = value.X;
}
set.Y
{
vector.Y = value.Y;
}
And it would be called as simply as Vector.X = 5. I thought up an alternative, using something like public float VectorX { set { vector.X = value; } } but I would prefer a more logical and object-orientated way. Is there?
It makes a BIG difference whether Vector2 is a class or a struct.
Since Vector2 is a class you can simply do
obj.Vector.X = 5;
having
public class MyClass
{
private Vector2 _vector; //Has to be private
public Vector2 Vector
{
get { return vector; }
set { vector = value; }
}
}
If, however Vector2 was a struct then you cannot modify the return value from the get. If you try you will get a compile error:
Cannot modify the return value of ... because it is not a variable.
You can work around this using the method you suggested with
public float VectorX
{
get { return _vector.X; }
set { _vector.X = value; }
}
public float VectorY
{
get { return _vector.Y; }
set { _vector.Y = value; }
}
or you could provide a wrapper class around Vector2 like:
class Vector2Wrapper
{
public Vector2 Vector;
}
and then store a Vector2Wrapper in MyClass like
public class MyClass
{
private Vector2Wrapper _vector2Wrapper;
public Vector2Wrapper VectorWrapper
{
get { return _vector2Wrapper; }
set { _vector2Wrapper= value; }
}
}
and you can then modify it like
obj.VectorWrapper.Vector.X = 5;
you can't specify a submethod to handle that partial set, because that set is handled by the Vector class and us thus out of your scope. the moment someone calls Myobject.Vector they are calling your get funcion, but when it moves on to .X they are calling the Vector.get_X function.
This may be easier to see by looking at the compiled code using the ILDasm tool, which reveals the actual method calls your properties make sugar out of.
Now, what you CAN do is to wrap certain properties, as mentioned. The result would like like so.
public class MyClass
{
private Vector2 _vector; //Has to be private
public Vector2 Vector
{
get { return vector; }
set { vector = value; }
}
public float VectorX
{
get { return _vector.X; }
set { _vector.X = value; }
}
public float VectorY
{
get { return _vector.Y; }
set { _vector.Y = value; }
}
}
Another option might be to use the pattern of INotifyPropertyChanged in your Vector class, raising an event every change which your MyClass can then listen to and react to, thus applying logic when child elements are updated.
There is also the option of using an indexer property
public class MyClass
{
public enum Axis { X, Y }
private Vector2 _vector; //Has to be private
public Vector2 Vector
{
get { return vector; }
set { vector = value; }
}
public float this[Axis axis]
{
get { return axis == Axis.X ? vector.x : vector.y; }
set
{
if(axis == Axis.Y)
{
// Special logic here
vector.Y = value;
}
if(axis == Axis.X)
{
// Special logic here
vector.X = value;
}
}
}
}
Because Vector2 is a struct, you are getting a COPY. You need to use the setter to set a new Vector2. There are 2 ways:
Vector2 v = myClass.Vector; //get a copy of the vector
v.X = 5f; // change its value
myClass.Vector = v; // put it back
I don't really like the following, but it's one statement:
myClass.Vector = new Vector2(2f, myClass.Vector.Y)
Inside MyClass, you can create a property that sets only the X value:
public float X {
get { return Vector.X; }
set {
Vector2 v = Vector;
v.X = value;
Vector = v;
}
}
(Vector can be an automatic property)

C# how to use the Parent class property in child class

I have following class which has Parent class Shapes which has property Radius and i am accessing this property into its child class(HeaxGon) but it gives me error in child class ( get or set accessor expected)
Please advise.
class Shapes
{
int _radius;
public int Radius
{
get { return _radius; }
set { _radius = value; }
}
}
class HeaxGon:Shapes
{
int points;
public void SetRadius
{
**Radius=20;**
}
}
I am guessing you are trying to create a function called SetRadius, in which case, this is what it should look like:
public void SetRadius(int radius)
{
this.Radius = radius;
}
Or if you really want to set it to 20 in all cases:
public void SetRadius()
{
this.Radius = 20;
}
You wrote it badly, it should look like this:
class Shapes
{
int _radius;
public int Radius
{
get { return _radius; }
set { _radius = value; }
}
}
class HeaxGon:Shapes
{
int points;
public void SetRadius()
{
Radius=20;
}
}
There's no need calling "this" like others have suggested.
Or simply work with the property you've already exposed in your base class
HeaxGon hg = new HeaxGon();
hg.Radius = 20;
This will call your setter you've specified in your base class (Shapes).
Make _radius protected, and then simply call this.Radius in the child class. So:
public class Shape
{
protected int _radius;
public int Radius
{
get { return _radius; }
set { _radius = value; }
}
}
public class Hexagon : Shape
{
int _points;
public void SetRadius(int radius)
{
this.Radius = radius;
}
}

Categories