Creating multiple / multinode properties in class - c#

I would like to understand and make my own classes in the way like the common rectangle:
Rectangle r1 = new Rectangle();
Size s = r1.Size;
int size = r1.Size.Width;
I don't want to use methods, just simple property values.
public partial class Rectangle
{
private Size _size;
public Size Size
{
get { return _size; }
set { _size = value; }
}
}
So how to create the Width, Height, etc. properties?
And if i would like to create longer chain? e.g.:
r1.Size.Width.InInches.Color.
etc.

Probably you'll find yourself saying: I knew it.
Class properties can be associations with other classes:
public class Size
{
public Size(double width, double height)
{
Width = width;
Height = height;
}
public double Width { get; }
public double Height { get; }
}
Now you'll be able to get rectangle's size as follows: rect1.Size.Width.
About providing the size unit, I wouldn't create an InInches property, but I would create an enumeration:
public enum Unit
{
Inch = 1,
Pixel
}
...and I would add a property to Size as follows:
public class Size
{
public Size(double width, double height, Unit unit)
{
Width = width;
Height = height;
Unit = unit;
}
public double Width { get; }
public double Height { get; }
public Unit Unit { get; }
}
...and if you need to perform conversions, you could easily implement them in Size too:
public class Size
{
public Size(double width, double height, Unit unit)
{
Width = width;
Height = height;
Unit = unit;
}
public double Width { get; }
public double Height { get; }
public Unit Unit { get; }
public Size ConvertTo(Unit unit)
{
Size convertedSize;
switch(unit)
{
case Unit.Inch:
// Calc here the conversion from current Size
// unit to inches, and return
// a new size
convertedSize = new Size(...);
break;
case Unit.Pixel:
// Calc here the conversion from current Size
// unit to pixels, and return
// a new size
convertedSize = new Size(...);
break;
default:
throw new NotSupportedException("Unit not supported yet");
break;
}
return convertedSize;
}
}
What you call chain is what in object-oriented programming is called composition.
Thus, you can associate Size with other class, and associate another class to the other one, and so on...

Related

I cannot set and call value using setter and getter

Learning Setter and Getter
I am making a console log app where I create a Box class and make an object and set values: width, height, and length using setter and getter. I was referencing an solution on github, but I haven't make it work yet. I don't know where I made mistake.
My Code
using System;
namespace ClassDemo2
{
class Box
{
private double _width;
private double _height;
private double _length;
public double Width
{
get { return _width; }
set { this._width = Width; }
}
public double Height
{
get { return _height; }
set { this._height = Height; }
}
public double Length
{
get { return _length; }
set {this._length = Length; }
}
public double volume()
{
return Width * Height * Length;
}
}
public class Program
{
static void Main(string[] args)
{
Box box = new Box();
//Set value
box.Width = 12;
box.Height = 12;
box.Length = 12;
//Get value
double width = box.Width;
double height = box.Height;
double length = box.Length;
Console.WriteLine("Box properties");
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Height: {0}", height);
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Volume: {0}", box.volume());
}
}
}
Console Window
The setters in the Box class aren't doing anything. The setters aren't assigning a value to the private fields in the Box class.
You may as well remove the fields altogether and use auto-implemented properties.
For example:
class Box
{
public double Width { get; set; }
public double Height { get; set; }
public double Length { get; set; }
public double Volume()
{
return Width * Height * Length;
}
}
class Box
{
public double Width { get; set; }
public double Height { get; set; }
public double Length { get; set; }
public double volume()
{
return Width * Height * Length;
}
}
Use Auto-Implemented Properties (https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties)

How to calculate area using Open closed principle C#

I am working with Open Closed principle of SOLID in C#. I have abstract class Shape which i want to used to calculate the area of different shapes. How to call areaCalculator class and how to pass different shapes. Here is my code.
public abstract class Shape
{
public abstract double Area();
}
public class Rectangle : Shape
{
public double Height { get; set; }
public double Width { get; set; }
public override double Area()
{
return Height * Width;
}
}
public class AreaCalculator
{
public double TotalArea(Shape[] shapes)
{
double area = 0;
foreach (var objShapes in shapes)
{
area += objShapes.Area();
}
return area;
}
}
I want to call areaCalculator class to calculate the area.
AreaCalculator _obj = new AreaCalculator();
Shape[] _shapes = new Shape[2];
var _result = _obj.TotalArea(_shapes);
Console.WriteLine(_result);
Console.ReadLine();
You need to create the rectangle objects and set their height and width for the calculation. If not the _shapes list is empty. Find below a sample of working code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ShapesStacjOverflow {
public abstract class Shape {
public abstract double Area();
}
public class Rectangle : Shape {
public double Height { get; set; }
public double Width { get; set; }
public override double Area() {
return Height * Width;
}
}
public class AreaCalculator {
public double TotalArea(Shape[] shapes) {
double area = 0;
foreach (var objShapes in shapes) {
area += objShapes.Area();
}
return area;
}
}
class Program {
static void Main(string[] args) {
AreaCalculator _obj = new AreaCalculator();
Shape[] _shapes = new Shape[2];
Rectangle rectangle1 = new Rectangle {
Width = 2,
Height = 3
};
Rectangle rectangle2 = new Rectangle {
Width = 1,
Height = 1
};
_shapes[0] = rectangle1;
_shapes[1] = rectangle2;
var _result = _obj.TotalArea(_shapes);
Console.WriteLine(_result);
Console.ReadLine();
}
}
}
Returning 7 as a result.
If you want to create other child shapes, those should override the Area() method, so for each of the objects created in the list, the corresponding Area() method would be applied.
Hope that helps.

How do I create nested properties? C#

As far as I read, creating nested properties don't seem to be possible in c#.
What I want to do is:
Callout callout = new Callout();
callout.Font.Size = 200;
This is the code I currently have
class Callout
{
// nested properties
}
I know how to create properties, but how do I create a nested property?
class Callout {
public Font Font {get;} = new Font();
}
class Font {
public int Size {get;set;}
}
public class Callout {
public Font Font {get;}
}
public struct Font {
public Font(int size) {
Size = size;
}
public int Size {get;}
}
If you really don't want to implement a separate class or struct, here's a tricky way to do what you are asking.
Note: Tricky != Recommended
class Callout : Callout.IFont
{
public interface IFont
{
int Size { get; set; }
}
protected int _fontSize = 0;
int IFont.Size
{
get
{
return _fontSize;
}
set
{
_fontSize = value;
}
}
public IFont Font => this;
}
var callout = new Callout();
callout.Font.Size = 100;

Is there a way to add additional values to the rectangle struct?

I want to add additional values to a rectangle. Like a "Name" string for example.
Something like this:
Rectangle MyRectangle = new Rectangle(Y, X, Width, Height, Name)
Is this possible?
There is two overload constructor function in Rectangle class.
public Rectangle(Point location, Size size);
public Rectangle(int x, int y, int width, int height);
But there isn't a constructor function parameter new Rectangle([int], [int], [int], [int], [string]) in Rectangle class.
You can try to use composite public Rectangle rect { get; set; } property in the class.
Then use constructor function to set Rectangle object and Name
public class CustomerRectangle
{
public Rectangle Rect { get; set; }
public string Name { get; set; }
public CustomerRectangle(int llx, int lly, int urx, int ury,string name)
{
Rect = new Rectangle(llx, lly, urx, ury);
Name = name;
}
}
then you can use
CustomerRectangle MyRectangle = new CustomerRectangle (Y, X, Width, Height, Name);
//MyRectangle.Name; use Name property
//MyRectangle.Rect; use Rectangle
I assume you are using a constructor from the System.Drawing namespace:
https://learn.microsoft.com/en-us/dotnet/api/system.drawing.rectangle?view=netframework-4.7.2
It is not possible to add an extra field to that structure. What you can do is create your own class or structure which does contain more .
public class NamedRectangle
{
public string Name { get; set; }
public double X { get; set; }
public double Y { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public NamedRectangle(double x, double y, double width, double height, string name)
{
Name = name;
X = x;
Y = y;
Width = width;
Height = height;
}
}
I've seen others have contributed good examples, but in case of Cannot inherit from sealed type error, following example might help you:
public class myRectangle
{
private Rectangle newRectangle = new Rectangle();
private string name;
public myRectangle Rectangle(Int32 Y, Int32 X, Int32 Height, Int32 Width, string name )
{
newRectangle.Y = Y;
newRectangle.X = X;
newRectangle.Height = Height;
newRectangle.Width = Width;
this.name = name;
return this;
}
}

Exchanging variables between 2 classes

Whenever I call the method Draw in Sprite, it won't draw it because X, Y, Width and Height are 0. :(
code:
class Sprite
{
protected int Y;// { get; set; }
protected int X;// { get; set; } { get; set; }
protected int Width;// { get; set; } { get; set; }
public int Height;// { get; set; } { get; set; }
protected Image image;// { get; set; } { get; set; }
public Sprite()
{
}
public void Draw(Graphics drawArea)
{
Image sImage = Image.FromFile("alien.jpg");
drawArea.Clear(Color.White);
drawArea.DrawImage(sImage, X, Y, Width, Height);
}
}
class User:Sprite
{
public User()
{
}
public User(int width, int height, int userWidth, int userHeight)
{
Sprite sprite = new Sprite();
Image UserImage = Image.FromFile("alien.jpg");
X = width;
Y = height;
Width = userWidth;
Height = userHeight;
image = UserImage;
}
}
ps: sprite.Draw is declared in another method in another class, but that all should work just fine.
Thanks for helping and probably saving me hours of time :)
Nick
EDIT
here is the subclass which gives the parameter and other stuff.
Alien mAlien;
User mUser;
protected int mLevel;
public gameLogic()
{
}
public gameLogic(int width, int height, int level)
{
mUser = new User(width / 2, height - 30, 30, 30);
mAlien = new Alien(width / 2, 5, 30, 30, "alien.jpg", 10 * level);
mLevel = level;
}
public void drawAll(Graphics drawArea)
{
Sprite sprite = new Sprite();
sprite.Draw(drawArea);
}
Im sorry for all these errors that'll probably occur, Im a new student :)
Try this:
public User(int width, int height, int userWidth, int userHeight)
{
Sprite sprite = new Sprite();
Image UserImage = Image.FromFile("alien.jpg");
sprite.X = width;
sprite.Y = height;
sprite.Width = userWidth;
sprite.Height = userHeight;
sprite.image = UserImage;
}
In order to access the fields of the sprite, you have to specify which Sprite object you are modifying. This is done by writing the name of the variable followed by .
EDIT: Just realized that there is another problem - your User class is inheriting from the Sprite class. Apparently your users are sprites, according to the comments, so you'll want to never instantiate a Sprite, and just use the User class instead:
class User:Sprite
{
public User(int width, int height, int userWidth, int userHeight)
{
Image UserImage = Image.FromFile("alien.jpg");
X = width;
Y = height;
Width = userWidth;
Height = userHeight;
image = UserImage;
}
}
Then instead of calling draw on a sprite in the other file, use the following:
User user = new User(x, y, width, height)
...
user.draw();
The key here is to make sure you are using new User... and not new Sprite - even if you are assigning to a Sprite variable e.g. Sprite s = new User(...);.
Then just make sure you call draw on the same object - the user.draw line. If you want to check that you're doing it right, try making Sprite abstract - abstract class Sprite - that way there will be compile errors if you try to instantiate Sprite instead of User.
EDIT 2: Ok, all you really need to do is change your calling code:
public void drawAll(Graphics drawArea)
{
mUser.draw(drawArea);
mAlien.draw(drawArea);
}
You are missing trailing '}' for both your classes, Sprite and User. Second you should call the base-Constructor in User's constructor:
public User(int width, int height, int userWidth, int userHeight)
: base(width, height, userWidth, userHeight, Image.FromFile("alien.jpg"))
{
}
Also you need to create a constructor for your base class which accepts these parameters.

Categories

Resources