C# - calling override method - c#

I am new to C# so please excuse gaps in my knowledge. In my code I have TWO types of foods Fresh and Regular.
When determining cost Fresh items use different FindCost method than Regular.
I am having trouble working out how to call the FindCost() method for Fresh Items.
I think i need to use the base keyword somehow s:
namespace Groceries
{
class Program
{
static void Main(string[] args)
{
PurchasedItem CheckoutItem4 = new FreshItem();
CheckoutItem4.Name = "Rump Steak";
CheckoutItem4.Condition = "Fresh";
CheckoutItem4.Price = 11.99;
CheckoutItem4.Weight = .8;
ArrayList invoiceArray = new ArrayList();
invoiceArray.Add(CheckoutItem1);
foreach (PurchasedItem checkoutItem in invoiceArray)
{
Console.WriteLine($"Quantity: {checkoutItem.Quantity} Weight: {checkoutItem.Weight}kg ");
}
Console.ReadLine();
}
}
public class GroceryItem
{
public string Name { get; set; }
public string Condition { get; set; }
public double Price { get; set; }
public GroceryItem()
{
}
public GroceryItem(string name, double price)
{
this.Name = name;
this.Price = price;
}
public static void Invoice()
{
Console.WriteLine();
}
}
public class PurchasedItem : GroceryItem
{
public int Quantity { get; set; }
public double Weight { get; internal set; }
public virtual double FindCost()
{
double cost = Quantity * Price * 1.1; //1.1 is GST
return cost;
}
}
public class FreshItem : PurchasedItem
{
public new double Weight { get; set; } //kg
public override double FindCost()
{
double cost = Weight * Price;
return cost;
}
}
}
any help appreciated

When you set Weight with the reference of type PurchasedItem :
CheckoutItem4.Weight = .8;
You set the field Weight declared in class PurchasedItem, but the method FindCost use the field Weight defined in class FreshItem that is not initialised. So, just remove de line : public new double Weight { get; set; } //kg. You do not need to redefine this field.

Your current code is correctly calling the right FindCost() method, but you've defined your classes in a poor way, and hiding with the new keyword can make it call the wrong method.
You should make GroceryItem abstract and have both of your classes directly inherit from this. Then GroceryItem can has an abstract FindCost() method. Also, if you're hiding a method with new then you're probably doing something wrong. You should find that this eliminates all uncertainty when calling FindCost().
Also, you should use decimal rather than double for financial calculations as double doesn't always accurately represent monetary values.
Here are the improved classes:
void Main()
{
List<GroceryItem> invoiceArray = new List<GroceryItem>()
{
new FreshItem() { Name = "Rump Steak", Price = 11.99m, Weight = 0.8 },
new PurchasedItem() { Name = "Cream", Price = 2.2m, Quantity = 1, Weight = 0.6 },
};
foreach (GroceryItem checkoutItem in invoiceArray)
{
if (checkoutItem is PurchasedItem purchasedItem)
{
Console.WriteLine($"Condition: {checkoutItem.Condition}; Quantity: {purchasedItem.Quantity}; Weight: {checkoutItem.Weight}kg");
}
else
{
Console.WriteLine($"Condition: {checkoutItem.Condition}; Weight: {checkoutItem.Weight}kg");
}
}
Console.ReadLine();
}
public abstract class GroceryItem
{
public string Name { get; set; }
public abstract string Condition { get; }
public double Weight { get; set; }
public decimal Price { get; set; }
public GroceryItem() { }
public GroceryItem(string name, decimal price)
{
this.Name = name;
this.Price = price;
}
public abstract decimal FindCost();
}
public class PurchasedItem : GroceryItem
{
public int Quantity { get; set; }
public override string Condition { get { return "Regular"; } }
public override decimal FindCost()
{
decimal cost = Quantity * Price * 1.1m; //1.1m is GST
return cost;
}
}
public class FreshItem : GroceryItem
{
public override string Condition { get { return "Fresh"; } }
public override decimal FindCost()
{
decimal cost = (decimal)Weight * Price;
return cost;
}
}

Related

Create object - product with name and price - best practice C#

The program should create a car which can have many parts and be able to set a part which always has a corresponding price to it.
My current car and part classes:
public class Car
{
public Car(string brand, string windshieldType, List<AdditionalCarParts> additionalCarParts) {
Brand = brand;
WindshieldType = windshieldType;
AdditionalCarParts = additionalCarParts;
}
public string Brand { get; set; }
public string WindshieldType { get; set; }
public int Price { get; set; }
public List<AdditionalCarParts> AdditionalCarParts { get; set; }
}
public class AdditionalCarParts
{
public AdditionalCarParts(PartData.PartNames part, int price) {
Part = part;
Price = price;
}
public PartData.PartNames Part { get; set; }
public int Price { get; set; }
}
public class PartData
{
public enum PartNames
{
EngineHeater,
SteeringWheelHeater,
HeadsUpDisplay,
Turbo
}
public static int EngineHeaterPrice() => 3000;
public static int SteeringWheelHeaterPrice() => 800;
public static int HeadsUpDisplayPrice() => 1200;
public static int TurboPrice() => 5000;
}
}
How to add one part to list of parts in my car, and that part has a price on it, for example:
var part = new AdditionalCarParts(PartData.PartNames.Turbo) and an object is created with price of 5000 set on it.
Should there even be a list of parts, or are there any better practices for this?
Thanks.
I would not use a class to hold the prices. I would use a data structure as a Dictionary to hold that info.
public class AdditionalCarParts
{
public AdditionalCarParts(PartData.PartNames part, int price) {
Part = part;
//Price = price;
}
public enum PartNames
{
EngineHeater,
SteeringWheelHeater,
HeadsUpDisplay,
Turbo
}
private Dictionary<PartNames, int> prices = new Dictionary<PartNames, int>() {
{ PartNames.EngineHeater, 3000 },
{ PartNames.SteeringWheelHeater, 800 },
{ PartNames.HeadsUpDisplay, 1200 },
{ PartNames.Turbo, 5000 },
};
public PartNames Part { get; set; }
public int Price(PartNames name) => prices[name];
}
"How to add one part to list of parts in my car" -> I find that adding it to the list is fine. As the prices are already pre-defined you would not need to provide the price in the class constructor.
If prices can change, you can handle that with a SetPrice method to update the dictionary. I would do:
public void SetPrice(PartNames name, int price) {
prices[name] = price;
}

Is it possible to acces to props of derived classes in a list a base class

I'm new to c# and trying to learn it.
I'm made this following code :
BASE CLASS :
namespace Computer
{
class Component
{
public string Name { get; set; }
public string Brand { get; set; }
public string Model { get; set; }
public string Category { get; set; }
public decimal Price { get; set; }
public Component()
{
}
public Component(string name, string brand, string model, string category, decimal price)
{
Name = name;
Brand = brand;
Model = model;
Category = category;
Price = price;
}
}
}
DERIVED CLASS
namespace Computer
{
class Processor : Component
{
public double Frequency { get; set; }
public Processor(string name, string brand, string model, string category, decimal price, double frequency)
: base(name, brand, model, category, price)
{
Frequency = frequency;
}
}
}
MAIN PROGRAM :
using System;
using System.Collections.Generic;
namespace Computer
{
class Program
{
static void Main(string[] args)
{
var computer = new Computer();
computer.ItemsList = new List<Component>
{
new Component("ASUS ROG Maximus XI Hero Z390", "Asus", "Maximus XI Hero (Wi-Fi)", "Motherboards", 399.99m),
new Processor("i9-9900k", "Intel", "BX80684I99900K", "Processors", 649.99m, 5.50),
};
foreach (var part in computer.ItemsList)
{
Console.WriteLine("Component Description : ");
Console.WriteLine("------------------------");
Console.WriteLine($"Name : {part.Name}");
Console.WriteLine($"Brand : {part.Brand}");
Console.WriteLine($"Model : {part.Model}");
Console.WriteLine($"Category : {part.Category}");
Console.WriteLine($"Price : ${part.Price}");
***Console.WriteLine(part.Frequency);***
Console.WriteLine("---\n");
}
}
}
}
I know that the base class doesn't have the Frequency prop, but is there a way to access to this prop for my new Processor instance? Or maybe I'm doing it badly?
Thank you for your advices!!

FlatBuffers KeyValuePair data type and schema definition

I have an object that I need to send over the network using TCP. I had this working fine, but I have now expanded on my implementation and am having trouble working out how to define my FlatBuffer schema.
The object to be sent is this:
public class Prediction
{
public PredictionMethod PredictionMethod { get; set; }
public NGramPrediction NGramPrediction { get; set; }
public DistancePrediction DistancePrediction { get; set; }
public int NGramOrder { get; set; }
}
PredictionMethod is an enum:
public enum PredictionMethod
{
Distance = 1,
NGram = 2,
}
NGramPrediction looks like this:
public class NGramPrediction
{
public KeyValuePair<char, int> Gram { get; set; }
public double Probability { get; set; }
public string Pattern { get; set; }
private int Total { get; set; }
private int Order { get; set; }
public NGramPrediction(Gram gram)
{
Total = gram.Total();
var orderedKeyPosibilities = gram.Posibilities.OrderByDescending(x => x.Value);
Gram = orderedKeyPosibilities.First();
Pattern = gram.Pattern;
Probability = (double)Gram.Value / Total;
Order = Pattern.Length;
}
}
Gram looks like this:
public class Gram
{
public string Pattern { get; set; }
public Dictionary<char, int> Posibilities { get; set; }
public Gram(List<char> posibilities, int initialValue = 0)
{
Posibilities = new Dictionary<char, int>();
foreach (var posibility in posibilities)
{
Posibilities.Add(posibility, initialValue);
}
}
public int Total()
{
var keys = Posibilities.Keys;
var total = 0;
foreach (var key in keys)
{
var value = Posibilities[key];
total += value;
}
return total;
// return keys.Sum(key => Posibilities[key]);
}
}
DistancePrediction looks like this:
public class DistancePrediction
{
public IIRVector3 Velocity { get; set; }
public float DeltaTime { get; set; }
public IIRVector3 Position { get; set; }
}
and finally, IIRVector3 looks like this:
public class IIRVector3
{
public IIRVector3()
{
X = 0;
Y = 0;
Z = 0;
}
public float X { get; set; }
public float Y { get; set; }
public float Z { get; set; }
}
I'm trying to define my schema for FlatBuffers:
enum FBPredictionMethod
{
Distance = 1,
NGram = 2
}
struct FBIIRVector3
{
X:float;
Y:float;
Z:float;
}
table FBDistancePrediction
{
Velocity:FBIIRVector3;
DeltaTime:float;
Position:FBIIRVector3;
}
table FBGram
{
Pattern:string;
Possibilities: ????
}
table FBNGramPrediction
{
Gram: ????
Probability:float;
Pattern:string;
Total:short;
Order:short;
}
table FBPrediction
{
PredictionMethod:FBPredictionMethod;
NGramPrediction:FBNGramPrediction;
DistancePrediction:FBDistancePrediction;
NGramOrder:short;
}
root_type FlatServerToClientMessage;
I think everything looks correct, but I have no idea what to do for the dictionaries...
FBGram.Possibilities should be a Dictionary<char, int> and FBGram should be KeyValuePair<char, int>.
Note: Gram's constructor takes a List<char> and an int as parameters, while the constructor for NGramPrediction takes a Gram as a parameter.
Could someone help me with my schema, please?
The KeyValuePair should be easy.. either just store them as two seperate fields, or use a struct KeyValuePair { key:byte; value:int; }
The Dictionary could be stored as Possibilities:[KeyValuePair] (using that same struct). If you wanted to save space if Possibilities can be large, then PossibilityKeys:[byte] and PossibilityValues:[int] will be a little bit more compact, but harder to read/write.

Auto increment ID C#

I am busy with a really small console application for c#. I am just new into c# and i'm only familiar with Java. My school gave the assignment to create a console application that simulates a car dealer. I already wrote a bunch of code to add cars by console. Things like brand and type and max speed are already implemented. The only thing i still need to realize is the auto creation and incremental of an ID for a car. It has the be unique of course.
My first approach was making the id field static and increment it in the constructor so that each time the object gets created the id gets ++;
I saw allot of people on stackoverflow doing allot of things but the solutions did not work or the where to big.
This is my code;
class Car : Vehicle
{
public string brand { get; set; }
public string type { get; set; }
public int maxSpeed { get; set; }
public double price { get; set; }
public static int carID { get; set; }
public Car(string _brand, string _type, int _maxspeed, double _price)
{
this.brand = _brand;
this.type = _type;
this.maxSpeed = _maxspeed;
this.price = _price;
this.carID++;
}
}
I added 3 cars to my list but the result is that all cars have ID 3;
Maybe someone could help me, thanks in advance.
class Car : Vehicle
{
public string brand { get; set; }
public string type { get; set; }
public int maxSpeed { get; set; }
public double price { get; set; }
public int carID { get; private set; }
public static int globalCarID;
public Car(string _brand, string _type, int _maxspeed, double _price)
{
this.brand = _brand;
this.type = _type;
this.maxSpeed = _maxspeed;
this.price = _price;
this.carID = Interlocked.Increment(ref globalCarID);
}
}
This maintains a global ID counter, and increments it atomically to make it thread-safe.
Note that the first ID assigned this way would be 1. You can initialize globalCarID with -1 to start at 0.
Just to remove static and add lock section for avoiding duplicate of Ids
class Car : Vehicle
{
private static object sync = new object();
private static int _globalCount;
public string brand { get; set; }
public string type { get; set; }
public int maxSpeed { get; set; }
public double price { get; set; }
public int carID { get; set; }
public Car(string _brand, string _type, int _maxspeed, double _price)
{
this.brand = _brand;
this.type = _type;
this.maxSpeed = _maxspeed;
this.price = _price;
lock (sync)
{
this.carID = ++globalCount;
}
}
}
A static variable is shared between all instances of the class.
Incrementing it in the constructor makes all instances of that class 'see' the last value assigned to the static variable.
You should create a normal instance carID variable (not static) and use a protected static variable defined in the base class to grab the current value at constructor time, assign to your carID instance variable and then increment the base class value.
class Vehicle
{
protected static int FakeID = 1;
}
class Car : Vehicle
{
public string brand { get; set; }
public string type { get; set; }
public int maxSpeed { get; set; }
public double price { get; set; }
public int carID { get; set; }
public Car(string _brand, string _type, int _maxspeed, double _price)
{
this.brand = _brand;
this.type = _type;
this.maxSpeed = _maxspeed;
this.price = _price;
this.carID = base.FakeID++;;
}
}
void Main()
{
Car a = new Car("xyz", "Auto", 120, 12000);
Car b = new Car("kwx", "Moto", 180, 8000);
Console.WriteLine(a.carID);
Console.WriteLine(b.carID);
}
Keep in mind that this will work correctly if your code doesn't use multithreaded access to the constructor. In case of multithreading you need to look at Interlocked.Increment

How do I correctly add mixes of different interfaces to different classes in C#?

I am trying to develop an API for some assessment software that will allow me to create questions consisting of the question text, multiple choice text and the choice index of the correct answer.
All questions are worth 10 points and the question can only be answered once.
For QuestionTypeA however, the user can change the number of retries and QuestionTypeB, the user can change both the number of retries and the score.
The reason for the CommonFunctions interface is so that I don't have to duplicate QuestionText, AddChoice and SetAnswer in each of the QuestionType interfaces.
But this does then leave me with empty interfaces, which I am not sure is correct?
Also, to instantiate an object I have to write
QuestionTypeA QTA = (QuestionTypeA)new Question();
I would rather the Question class dealt with the cast so that the user can then just type:
QuestionTypeA QTA = new Question();
How can achieve this?
Thanks
Andrew
public interface IRetryable
{
int Retries { set; get; }
}
public interface IScoreable
{
int Score { set; get; }
}
public interface CommmonFunctions
{
string QuestionText { set; get; }
void AddChoice(string ChoiceText);
int SetAnswer { set; get; }
}
public interface QuestionTypeA : CommmonFunctions, IRetryable
{
}
public interface QuestionTypeB : CommmonFunctions, IRetryable, IScoreable
{
}
public interface QuestionTypeC : CommmonFunctions
{
}
class Question : CommmonFunctions
{
private List<string> Choices;
public Question()
{
Choices = new List<string>();
Retries = 1;
Score = 10;
}
public string QuestionText { set; get; }
public void AddChoice(string ChoiceText)
{
Choices.Add(ChoiceText);
}
public int SetAnswer { set; get; }
public int Retries { set; get; }
public int Score { set; get; }
}
It seems you are over-thinking things...
Just keep it simple.
var question1 = new QuestionTypeA();
var question2 = new QuestionTypeB();
public interface IRetryable
{
int Retries { set; get; }
}
public interface IScoreable
{
int Score { set; get; }
}
public abstract class Question
{
private List<string> choices = new List<string>();
public string QuestionText { set; get; }
public int SetAnswer { set; get; }
public void AddChoice(string choiceText)
{
choices.Add(choiceText);
}
}
public class QuestionTypeA : Question, IRetryable
{
public QuestionTypeA()
{
Retries = 1;
}
public int Retries { set; get; }
}
public class QuestionTypeB : Question, IScoreable
{
public QuestionTypeB()
{
Score = 0;
}
public int Score { set; get; }
}
Thanks ASh for your response.
I guess it would make sense to incorporate in them in to the interface.
I now need to add another interface (IShuffle) to QuestionTypeA as below.
interface IShuffable
{
void Shuffle();
}
public class QuestionTypeA : Question, IRetryable, IShuffable
{
public QuestionTypeA()
{
Retries = 1;
}
public int Retries { set; get; }
public void Shuffle()
{
// Code to implement shuffling the choices
}
}
Shuffle has nothing to do with QuestionType B or C, so Ideally I would like to hide this method from instances of QuestionType B and C so that it doesn't appear in intellisense.
Any attempt to call the shuffle method on instances of either QuestionTypeB or C, should then result in a standard compiler error i.e "QuestionTypeB does not contain a definition for shuffle ...".
Would it be better to use interfaces for this solution given the above? or something else?
Thanks Andrew
since all question have at least score 10 and 0 or more retries, why not include that info in the common interface like this?
public interface CommmonFunctions
{
string QuestionText { set; get; }
void AddChoice(string ChoiceText);
int SetAnswer { set; get; }
int Score { set; get; }
bool ScoreReadonly {get;}
int Retries { set; get; }
bool RetriesReadonly {get;}
}
ScoreReadonly and RetriesReadonly show if score or retries count can be changed outside class:
class Question : CommmonFunctions
{
private List<string> Choices;
public Question()
{
Choices = new List<string>();
_retries = 1;
_score = 10;
}
public string QuestionText { set; get; }
public void AddChoice(string ChoiceText)
{
Choices.Add(ChoiceText);
}
public int SetAnswer { set; get; }
private int _retries;
public int Retries
{
get{ return _retries; }
set
{
if (!RetriesReadonly)
_retries = value;
}
}
private int _score;
public int Score
{
get{ return _score; }
set
{
if (!ScoreReadonly)
_score = value;
}
}
public virtual bool ScoreReadonly {get{return false;}}
public virtual bool RetriesReadonly {get{return false;}}
}
UPDATE
public interface IShuffable
{
void Shuffle();
}
class QuestionTypeA : Question, IShuffable
{
// question of type A can't change score
public override bool ScoreReadonly { get {return true;}}
public void Shuffle()
{
// Code to implement shuffling the choices
}
}
class QuestionTypeB : Question {}

Categories