Trying to complete an assignment for class and I can get correct output when assigning the parameters together but when trying to assign the values individually I can't get a price. I have a feeling it's an extremely easy fix but I've been doing assignments all day and my brain feels like jello. Not looking for an answer so much as a hint to push my to the correct answer. Thanks!
using static System.Console;
using System;
class PhotoDemo
{
static void Main()
{
Photo standardPhoto = new Photo();
standardPhoto.Width = 8;
standardPhoto.Height = 9;
WriteLine(standardPhoto.ToString());
Photo customPhoto = new Photo(10, 12);
WriteLine(customPhoto.ToString());
MattedPhoto mattedPhoto = new MattedPhoto(8, 9, "Blue");
WriteLine(mattedPhoto.ToString());
FramedPhoto framedPhoto = new FramedPhoto(8, 9, "Wood", "Modern");
WriteLine(framedPhoto.ToString());
}
}
public class Photo
{
public Photo(){}
public int Width{get; set;}
public int Height{get; set;}
protected double Price{get; set;}
public Photo(int width, int height)
{
Width = width;
Height = height;
if(width == 8 && height == 10)
{
Price = 3.99;
}
else if(Width == 10 && Height == 12)
{
Price = 5.99;
}
else
{
Price = 9.99;
}
}
public override string ToString()
{
string output = String.Format("Width: {0}, Height: {1}, Price: {2}", Width, Height, Price.ToString("C"));
return output;
}
}
public class MattedPhoto : Photo
{
public MattedPhoto(){}
public string Color {get; set;}
public MattedPhoto(int width, int height, string color) : base(width, height)
{
width = Width;
height = Height;
color = Color;
if(width == 8 && height == 10)
{
Price = 3.99 + 10;
}
else if(width == 10 && height == 12)
{
Price = 5.99 + 10;
}
else
{
Price = 9.99 + 10;
}
}
public override string ToString()
{
string output = String.Format("Width: {0}, Height: {1}, Price: {2}, Color: {3}", Width, Height, Price.ToString("C"), Color);
return output;
}
}
public class FramedPhoto : Photo
{
public FramedPhoto(){}
public string Material{get; set;}
public string Style{get; set;}
public FramedPhoto(int width, int height, string material, string style) : base(width, height)
{
width = Width;
height = Height;
material = Material;
style = Style;
if(width == 8 && height == 10)
{
Price = 3.99 + 25;
}
else if(width == 10 && height == 12)
{
Price = 5.99 + 25;
}
else
{
Price = 9.99 + 25;
}
}
public override string ToString()
{
string output = String.Format("Width: {0}, Height: {1}, Price: {2}, Material: {3}, Style: {4}", Width, Height, Price.ToString("C"), Material, Style);
return output;
}
}```
Price calculation is doing only in the constructors with parameters (so only when you create an object). When you use parameter-less one, then the price isn't calculated (even if you set width and height later). You can:
create a separate method which takes width and height as parameters and recalculates price
modify price getter, to automatically recalculate price every time you ask for it
Related
I have parent class Product and child class DairyProduct and i want to set all fields and properies of parent class in child class, but i do not want to do a lot of new constructors.
How to set properties (name, price and weight) in DairyProduct without a new constructor?
Also codes for example:
Parent class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Task1
{
public class Product
{
private string _name;
public string Name { get => _name; set => _name = value; }
private float _price;
public float Price
{
get => _price;
set => _price = value < 0 ? throw new ArgumentException() : _price = value;
}
private float _weight;
public float Weight
{
get { return _weight; }
set { _weight = value < 0 ? throw new ArgumentException() : _weight = value; }
}
public Product() : this(null, default, default) {}
public Product(string name, float price, float weight)
{
Name = name;
Price = price;
Weight = weight;
}
public virtual void Discount(float percentage)
{
if (percentage <= 100) Price = Price * (100 - percentage) / 100;
else throw new ArgumentException();
}
public override string ToString()
{
return string.Format("Name: {0}; Price: {1}; Weight: {2};", Name, Price, Weight);
}
public override bool Equals(object obj)
{
if (obj.GetType() != typeof(Product))
{
return false;
}
else
{
Product p = (Product)obj;
return p.Name == Name && p.Price == Price && p.Weight == Weight;
}
}
}
}
Child class
using System;
namespace Task1
{
class DairyProduct : Product
{
public readonly DateTime ExpirationDate;
private int _daysToExpiration;
private bool _isFresh;
public DairyProduct()
{
_daysToExpiration = 90;
ExpirationDate = DateTime.Now.AddDays(_daysToExpiration);
_isFresh = true;
}
public DairyProduct(int daysToExpiration)
{
ExpirationDate = DateTime.Now.AddDays(daysToExpiration);
_isFresh = true;
}
public DairyProduct(DateTime experationDate, int daysToExpiration)
{
_daysToExpiration = daysToExpiration;
ExpirationDate = experationDate;
CheckExpirationDate();
}
public void CheckExpirationDate() => _isFresh = (ExpirationDate - DateTime.Now).Days > 0;
public override void Discount(float percentage)
{
CheckExpirationDate();
if (_isFresh)
{
float discontPersentage = (float)(1 - ((ExpirationDate - DateTime.Now).Days) / _daysToExpiration) + percentage / 100;
if (discontPersentage >= 1)
{
Price = 0;
}
else
{
Price *= discontPersentage;
}
}
else
{
Price = 0;
}
}
public override string ToString()
{
return string.Format("Name: {0}; Price: {1}; Weight: {2}; Expiration date: {3}", Name, Price, Weight, ExpirationDate);
}
}
}
You can include the parent properties with the child constructor parameters. Then call the base() method to initialise the parent properties.
public DairyProduct(string name, float price, float weight) :
base(name, price, weight)
{
_daysToExpiration = 90;
ExpirationDate = DateTime.Now.AddDays(_daysToExpiration);
_isFresh = true;
}
public DairyProduct(string name, float price,
float weight, int daysToExpiration) :
base(name, price, weight)
{
ExpirationDate = DateTime.Now.AddDays(daysToExpiration);
_isFresh = true;
}
public DairyProduct(string name, float price, float weight,
DateTime experationDate, int daysToExpiration) :
base(name, price, weight)
{
_daysToExpiration = daysToExpiration;
ExpirationDate = experationDate;
CheckExpirationDate();
}
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)
I am having a problem with my homework. I have an instance variable price that is supposed to have a get method and no set method. I have this price variable calculated and assigned through a constructor. I noticed that if you change either the width or height value to another number in Main, the price variable does not change. I added a updatePrice() method that will work if explicitly called in Main but would like to have it implemented automatically through the height/width set methods. I can't get it to work right now.
Explicit call to updatePrice() after changing width variable which works.
using System;
using static System.Console;
class Photo
{
private int width { get; set; }
private int height { get; set; }
protected double price;
public int Width {
get
{
return width;
}
set
{
updatePrice(value, height);
width = value;
}
}
public int Height {
get
{
return height;
}
set
{
updatePrice(width, value);
height = value;
}
}
public Photo(int width, int height)
{
this.width = width;
this.height = height;
if (width == 8 && height == 10)
price = 3.99;
else if (width == 10 && height == 12)
price = 5.99;
else
price = 9.99;
}
public virtual double Price
{
get
{
return price;
}
}
public String ToString()
{
return GetType() + " with a width of " + width + " and a height of " + height +
" with a base price of " + Price.ToString("C2");
}
// used to be updatePrice() w/ no parameters
public void updatePrice(int width, int height)
{
if (width == 8 && height == 10)
price = 3.99;
else if (width == 10 && height == 12)
price = 5.99;
else
price = 9.99;
}
static void Main()
{
Photo photo = new Photo(10, 12);
WriteLine(photo.ToString());
photo.height = 4;
// updatePrice();
WriteLine(photo.ToString());
}
}
Photo with a width of 10 and a height of 12 with a base price of $5.99
// change height to 4
Photo with a width of 10 and a height of 4 with a base price of $5.99
// price should be $9.99
Here is your code refactored as adviced in my comment of the question, with updatePrice marked protected virtual to allow polymorphism, added .Name in ToString, and I removed useless accessors of private fields:
class Photo
{
private int width;
private int height;
protected double price;
public int Width {
get
{
return width;
}
set
{
width = value;
updatePrice();
}
}
public int Height {
get
{
return height;
}
set
{
height = value;
updatePrice();
}
}
public Photo(int width, int height)
{
this.width = width;
this.height = height;
updatePrice();
}
public virtual double Price
{
get
{
return price;
}
}
public override string ToString()
{
return GetType().Name +
" with a width of " + width +
" and a height of " + height +
" with a base price of " + Price.ToString("C2");
}
protected virtual void updatePrice()
{
if (width == 8 && height == 10)
price = 3.99;
else if (width == 10 && height == 12)
price = 5.99;
else
price = 9.99;
}
}
So you don't need to call updatePrice from outside:
static void Main()
{
Photo photo = new Photo(10, 12);
WriteLine(photo.ToString());
photo.height = 4;
WriteLine(photo.ToString());
}
Instead of updating the price, calculate the price dynamically in the Price property. Like this you are sure that it always reflects the current state.
public virtual double Price
{
get
{
if (width == 8 && height == 10) return 3.99;
if (width == 10 && height == 12) return 5.99;
return 9.99;
}
}
I just made this speed test with the property as above:
var stopWatch = new Stopwatch();
stopWatch.Start();
for (int i = 0; i < 1_000_000; i++) {
photo.Height = 4;
double price = photo.Price;
photo.Height = 10;
price = photo.Price;
}
stopWatch.Stop();
Console.WriteLine("Elapsed ms: " + stopWatch.ElapsedMilliseconds);
Note that it calculates the price 2 million times. It takes 67 ms to execute! So it is not worth the effort to try to optimize this calculation. You are only saving a few nanoseconds. But putting the calculation in the property simplifies you code and makes it more reliable.
Note also that you must override the existing ToString method inherited from object.
public override string ToString()
{
return $"{GetType()}: width = {width}, height = {height}, base price = {Price:C2}";
}
Then you can print the photo with
WriteLine(photo);
as WriteLine automatically uses this method now. I also used string interpolation. This is more readable than string concatenation.
How can I call the parameter which is inside the method instance in the other class, as I want to make a calculation with the method and display it.
class Box
{
int width = 10;
int height = 15;
public int Area(int Area)
{
Area = width * height;
return Area;
}
public int Perimeter(int Para)
{
Para = 2 * (height + width);
return Para;
}
}
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
static void Main(string[] args)
{
Box b = new Box();
b.Area(Area);
b.Perimeter(Para);
Console.ReadLine();
}
It is giving me en error on b.Area(Area); and b.Perimeter(Para);
Maybe you wanted to do this:
class Program
{
static void Main(string[] args)
{
Box box = new Box(10, 15);
Console.WriteLine("Area is: " + box.CalculateArea());
Console.WriteLine("Perimeter is: " + box.CalculatePerimeter());
Console.ReadLine();
}
}
public class Box
{
public int Width { get; set; }
public int Height { get; set; }
public Box(int width, int height)
{
Width = width;
Height = height;
}
public int CalculateArea()
{
return Width * Height;
}
public int CalculatePerimeter()
{
return 2 * (Width + Height);
}
}
I have an app with the main window which contains a rectangle and a button that leads to another window in which the user enters information. After entering info, user clicks on a button and it returns him to the main window and changes the size accordingly. What I am trying to achieve is to return the ActualHeight and ActualWidth to the rectangle if a user presses the button in the main window again, kind of a refresh of rectangle.
All the code is in the Main Window Button click event. If you need any specific information about the code, i will gladly give it to you.
private void buttonStart_Click(object sender, RoutedEventArgs e)
{
Questionnaire q = new Questionnaire();
q.ShowDialog();
var size = q.textBoxNumberOfEmployees.Text;
if (int.Parse(size) > 5 && int.Parse(size) < 15)
{
Rect1.Height = Rect1.ActualHeight - 10;
Rect1.Width = Rect1.ActualWidth - 5;
}
else if (int.Parse(size) > 15 && int.Parse(size) < 30)
{
Rect1.Height = Rect1.ActualHeight - 15;
Rect1.Width = Rect1.ActualWidth - 10;
}
else if (int.Parse(size) > 30 && int.Parse(size) < 100)
{
Rect1.Height = Rect1.ActualHeight - 30;
Rect1.Width = Rect1.ActualWidth - 15;
}
else
{
Rect1.Height = Rect1.ActualHeight;
Rect1.Width = Rect1.ActualWidth;
}
You can store the original height and width of rectangle in variables in form load. Use those variables to make rectangle to original size bebore opening new window in button click.
Following code goes at the top inside your form.
private int rect1width;
private int rect1height;
In your form__load you write this at the end.
rect1width = Rect1.ActualWidth;
rect1height = Rect1.ActualHeight;
In your button click code following code goes at top.
Rect1.Width = rect1width;
Rect1.Height = rect1height;
Here is some seemingly long code, but it uses an MVC type design pattern and compounds with the state pattern. The only thing really missing to make it true MVC is Observers and observable interfaces that would subscribe to the Questionnaire.
public interface RectangleState
{
int myHeight { get; set; }
int myWidth { get; set; }
}
public class RectangleModel
{
private static Rectangle Rect1;
public RectangleModel(Rectangle rect1 )
{
Rect1 = rect1;
}
private RectangleState state;
public RectangleState State
{
get
{
return state;
}
set
{
state = value;
ModifyState(value.myHeight, value.myWidth);
}
}
private void ModifyState(int Height, int Width)
{
Rect1.Height = Height;
Rect1.Width = Width;
}
}
public class SmallState : RectangleState
{
public int myHeight { get; set; } = 20;
public int myWidth { get; set; } = 80;
}
public class MediumState : RectangleState
{
public int myHeight { get; set; } = 25;
public int myWidth { get; set; } = 90;
}
public class LargeState : RectangleState
{
public int myHeight { get; set; } = 35;
public int myWidth { get; set; } = 120;
}
public class NormalState : RectangleState
{
public int myHeight { get; set; } = 30;
public int myWidth { get; set; } = 100;
}
Now all you need to do is plug in the conditions:
RectangleModel RM = new RectangleModel(myRectangle); // store this in your class as property;
int size = 0;
int.TryParse(q.textBoxNumberOfEmployees.Text, out size);
if (size > 5 && size < 15)
{
RM.State = new SmallState();
}
else if (size > 15 && size < 30)
{
RM.State = new MediumState();
}
else if (size > 30 && size < 100)
{
RM.State = new LargeState();
}
else
{
RM.State = new NormalState();
}
If later you decide you want to change the default values on any of these you can change them. If you wish to add a new Rectangle shape or size you can add it. If you wish to create an adapter to further modify the rectangle, you can do so. This is a nice pattern. I know the answer looks overdone, but I think you will find it works solidly and is quite flexible when plugged into the code that accesses your questionaire.