Access constructor value - c#

I am trying to access value in my code. I have two classes, carex and engine.
The engine class has the following code:
public class Engine
{
public string Size;
public int HorsePower;
public float FuelConsumtionRate;
public Engine()
{
}
public Engine(string cylinder, int hp, float fuelRate)
{
Size = cylinder;
Console.WriteLine($"Engine type: {cylinder}");
HorsePower = hp;
Console.WriteLine($"Horse power: {hp} hp");
FuelConsumtionRate = fuelRate;
Console.WriteLine($"Fuel consumption: {fuelRate} l/h");
}
}
The carex class has the following code:
public class CarEx
{
string Manfacturer;
string RegistrationNr;
float Fuel;
float Speed;
bool IsRunning;
public CarEx(string manuf, float fuel, string regNr)
{
Manfacturer = manuf;
this.Fuel = fuel;
RegistrationNr = regNr;
Console.WriteLine("_____________________________________________________");
Console.WriteLine($"Manufacturer; {manuf}, Fuel amount: {fuel}l, License: {regNr}");
Console.WriteLine("______________________________________________________");
}
public void ChooseEngineType()
{
Engine v4 = new Engine("v4", 200, 0.7f);
}
public void FillFuel(float amount)
{
Fuel += amount;
/*
Fuel -= 0.7f;
*/
}
public static void RunCar()
{
CarEx car1 = new CarEx("Saab", 10, "1234DD");
car1.CallCustomer();
Console.WriteLine($"Maker: {car1.Manfacturer}");
Console.WriteLine($"Registration nr: {car1.RegistrationNr}");
}
}
I would like to replace the hard coded fuel consumption rate
Fuel -= 0.7f;
which I commented out with the value set in the engine constructor so its not hard coded any more.
What am I missing out on?

Your ChooseEngineType method creates an Engine object, but it is stored in a local variable which ceases to exist as soon as the method ends.
Change that variable to a field or property Engine engine at class level, and then you can use engine and its property engine.FuelConsumtionRate in all methods.
(PS, the proper spelling of that property would be FuelConsumptionRate)

Assuming that the fuel consumption rate is constant, you can use a constant that is privately accessible in the class you've declared by doing this:
private const float fuelConsumptionRate = 0.7f;
and then use it in your code so that you do not hard-code the changes. Otherwise, if the rate is bound to change, you'll need to store either the Engine itself (most recommended), or just the consumption rate in a private field like this:
private Engine engine;
// or
private float fuelConsumptionRate;
// the rest of your class' code
public void ChooseEngineType()
{
float rate = 0.7f;
Engine v4 = new Engine("v4", 200, rate);
engine = v4;
// or
fuelConsumptionRate = rate;
}

Added a new constructor for fuel rate in Engine class
public class Engine
{
public static string Size;
public static int HorsePower;
public static float FuelConsumtionRate;
//Constructor to set fuel reate
public Engine(float fuelRate)
{
FuelConsumtionRate = fuelRate;
}
public Engine(string cylinder, int hp, float fuelRate)
{
Size = cylinder;
Console.WriteLine($"Engine type: {cylinder}");
HorsePower = hp;
Console.WriteLine($"Horse power: {hp} hp");
FuelConsumtionRate = fuelRate;
Console.WriteLine($"Fuel consumption: {fuelRate} l/h");
}
And in the carex class:
public class CarEx
{
string Manfacturer { get; set; }
string RegistrationNr { get; set; }
float Fuel;
float Speed;
bool IsRunning;
public CarEx(string manuf, float fuel, string regNr)
{
Manfacturer = manuf;
this.Fuel = fuel;
RegistrationNr = regNr;
Console.WriteLine("_____________________________________________________");
Console.WriteLine($"Manufacturer; {manuf}, Fuel amount: {fuel}l, License: {regNr}");
Console.WriteLine("______________________________________________________");
}
public void ChooseEngineType()
{
Engine v4 = new Engine("v4", 200, 0.7f);
}
public void Accelerate()
{
Speed += 6.0f;
//Fuel rate set for v4 object
Fuel -= Engine.FuelConsumtionRate;
}

Related

Calling an overridden function from a base constructor

It makes sense that I should not call an overridden function from a base constructor, since the derived class is not yet constructed.
But I want to use this design pattern, where each derived class provides methods for calculating the properties of the base class since the properties should be immutable and assigned at the constructor.
Shape.cs
public abstract class Shape
{
protected Shape()
{
Area = 0f;
Center = Vector2.Zero;
const int n = 36;
float du = 1/(float)n, dv = 1/(float)n;
for (int i = 0; i < n; i++)
{
float u = (i+0.5f)*du;
for (int j = 0; j < n; j++)
{
float v = (i+0.5f)*dv;
float f = GetAreaElement(u, v);
// Warning: Remove this call from a constructor to the overridable 'GetAreaElement' method.
Area += f*du*dv;
Center += GetPosition(u, v)*f*du*dv;
// Warning: Remove this call from a constructor to the overridable 'GetPosition' method.
}
}
Center /= Area;
}
public abstract Vector2 GetPosition(float u, float v);
protected abstract float GetAreaElement(float u, float v);
public float Area { get; }
public Vector2 Center { get; }
}
public class Circle : Shape
{
public Circle(float radius)
{
Radius=radius;
}
public float Radius { get; }
public override Vector2 GetPosition(float u, float v)
{
float r = u*Radius, θ = (float)(2*Math.PI)*v;
return new Vector2(
r*(float)Math.Cos(θ),
r*(float)Math.Sin(θ));
}
protected override float GetAreaElement(float u, float v)
{
return u*Radius;
}
}
public class Rectangle : Shape
{
public Rectangle(float side1, float side2)
{
Side1=side1;
Side2=side2;
}
public float Side1 { get; }
public float Side2 { get; }
public override Vector2 GetPosition(float u, float v)
{
return new Vector2((u-0.5f)*Side1, (v-0.5f)*Side2);
}
protected override float GetAreaElement(float u, float v)
{
return Side1*Side2;
}
}
So what is the solution here? I want to use the base constructor to define the properties, and the calculation depends on the implementation of the derived class.
Workaround 1 - Future calculator
A workaround would be to provide a protected function that calculates the properties, each to be called from each constructor of the derived class, but there is no enforcement here. If one class forgets to call the calculator function the whole thing falls apart. And the properties are now private set which is not immutable really.
public abstract class Shape
{
protected void Calculate()
{
...
float f = GetAreaElement(u, v);
...
Center += GetPosition(u, v)*f*du*dv;
...
}
public abstract Vector2 GetPosition(float u, float v);
protected abstract float GetAreaElement(float u, float v);
public float Area { get; private set; }
public Vector2 Center { get; private set; }
}
public class Circle : Shape
{
public Circle(float radius)
{
Radius=radius;
base.Calculate();
}
public float Radius { get; }
public override Vector2 GetPosition(float u, float v)
{
...
}
protected override float GetAreaElement(float u, float v)
{
...
}
}
Workaround 2 - Function delegates
Another workaround would be to supply the delegates to the required function implementations as arguments to the base class constructor.
public delegate float AreaFactor(float u, float v);
public delegate Vector2 PositionFunc(float u, float v);
public abstract class Shape
{
protected Shape(AreaFactor a, PositionFunc p)
{
this.GetAreaElement = a;
this.GetPosition = p;
...
float f = a(u, v);
this.Center += p(u, v)*f*du*dv;
...
}
public float Area { get; }
public Vector2 Center { get; }
public AreaFactor GetAreaElement { get; }
public PositionFunc GetPosition { get; }
}
public class Circle : Shape
{
public Circle(float radius)
: base(
(u, v) => u*radius,
(u,v)=>
{
float r = u*radius, θ = (float)(2*Math.PI)*v;
return new Vector2(
r*(float)Math.Cos(θ),
r*(float)Math.Sin(θ));
})
{
Radius=radius;
}
public float Radius { get; }
}
This seems a bit clunky to me, and I am not sure I like the function delegate properties, instead of overridden methods.
Question/Challege
Can [SO] provide some other ways of achieving the above-stated goals
Base properties are immutable
Base properties are calculated at the constructor based on the implementation details of the derived classes.
Each derived class holds its own immutable properties used to describe the derived class.
One option is to, instead of calculating the Area and Center in the constructor, lazily calculate them in the property getter. It will require a backing field to know if the property has been calculated or not, but it will get rid of the warning.
It also seems odd to me that you don't pass the center to the Shape constructor, but I don't fully understand the design you're using.
My preference is to go with Option 2 - passing to the base constructor the methods to generate the derived properties. It does satisfy all your requirements. If aesthetics is a concern, perhaps using a Func might make the code easier to read. The key is that the Func's are static methods, which should not be a problem since they calculate immutable properties of the object.
void Main()
{
var square = new Square(5);
}
public abstract class Shape
{
protected Shape(Func<int> areaFunc)
{
Area = areaFunc();
}
public int Area { get; }
}
public class Square : Shape
{
public Square(int side): base( () => CalcArea(side) )
{
Side = side;
}
static int CalcArea(int side) => side * side;
public int Side { get; }
}

I've multiple classes which differs only a bit. Is there a better approach?

still learning my way thorugh unity and c# i got the following problem.
Ive multiple classes which differs only a bit. Iam faceing now the problem that ive some methods which only needs the ID value of the class and name for my buildingsystem but i cant pass the list over as the list passed is always from a different type of object. Is there a better approach for this
Here the 2 sample classes + the function i want to pass the list later on to get just the ID + Name value of the class.
Class Electricty:
public class Electricity
{
public int electricityID;
public string electricityName;
public float electricityPower;
public double electricityCost;
public Sprite electricitySprite;
public bool isPlaced;
public Vector3 electricityPosition;
public Electricity(int id, string name, float power, double cost, Sprite sprite, bool placed, Vector3 position)
{
this.electricityID = id;
this.electricityName = name;
this.electricityPower = power;
this.electricityCost = cost;
this.electricitySprite = sprite;
this.isPlaced = placed;
this.electricityPosition = position;
Debug.Log("New Electricity created");
}
Class Security:
public class Security
{
public int securityID;
public string securityName;
public double securityCost;
public Sprite securitySprite;
public Security(int id, string name, double cost, Sprite sprite)
{
this.securityID = id;
this.securityName = name;
this.securityCost = cost;
this.securitySprite = sprite;
Debug.Log("New Security created");
}
}
Function ive where the class List later will be passed to
public void StartBuildingSystem(List<Electricty> electricityList, int count, string name)
{
uiPhone.SetActive(false);
uiPlacement.SetActive(true);
PlacingAreas(GetActiveBluePrint(name), GetActiveType(electricityList, name));
activeBuildingType = GetActiveBuildingType(name);
//uiPlacement.SetActive(false);
}
public void StartBuildingSystem(List<Security> securityList, int count, string name)
{
uiPhone.SetActive(false);
uiPlacement.SetActive(true);
PlacingAreas(GetActiveBluePrint(name), GetActiveType(securityListList, name));
activeBuildingType = GetActiveBuildingType(name);
//uiPlacement.SetActive(false);
}
Could anyone give me any idea what would be a better approach so i dont have to make multiple functions which does except same just get a different list passed over.
Thank you.
The easiest thing would probably we a Parent Class from which both of your classes inherit.
Parent Class:
// System Base Class
public class System {
// Member Variables.
[SerializeField]
private int id;
[SerializeField]
private string name;
[SerializeField]
private double cost;
[SerializeField]
private Sprite sprite;
// Constructor.
public Security(int id, string name, double cost, Sprite sprite) {
// Set Member Variables.
this.id = id;
this.name = name;
this.cost = cost;
this.sprite = sprite;
Debug.Log("New System created");
}
}
After you've created that Parent Class you can inherit from it and then set the values in your Child Class.
Electricity Child Class:
public class Electricity : System {
// Member Variables.
[SerializeField]
private bool isPlaced;
[SerializeField]
private Vector3 position;
// Constructor.
public Electricity(int id, string name, float power, double cost,
Sprite sprite, bool placed, Vector3 position) {
// Set Member Variables.
this.id = id;
this.name = name;
this.power = power;
this.cost = cost;
this.sprite = sprite;
this.isPlaced = placed;
this.position = position;
Debug.Log("New Electricity created");
}
}
Additionally you can use use the function for both Child Classes. If you use Generic Methods (T).
public void StartBuildingSystem(List<T> list, int count, string name) {
uiPhone.SetActive(false);
uiPlacement.SetActive(true);
PlacingAreas(GetActiveBluePrint(name), GetActiveType(list, name));
activeBuildingType = GetActiveBuildingType(name);
//uiPlacement.SetActive(false);
}

Overriding Static Constants in Derived Classes in C#

First off, I know that you can't override static properties or functions in C#.
Here's what I need.
public abstract class Effect
{
public virtual const float duration = 1.0f;
public void boo() {
//do some stuff with duration
}
public void foo() {
//do some other stuff with duration
}
}
public class EffectA : Effect
{
public override const float duration = 3.0f;
}
There's some other stuff in the base and derived class, but the part that I'm having trouble with is this static constant. I need to refer it from other sections of code WITHOUT an instance, e.g. EffectA.duration. A function/property would also be fine, but those also can not be overriden if static.
I've seen similar questions, but all the answers seem to involve non-static solutions, i.e. instead of making it a static function, make it an instance function. In my case, in the places where I want to query EffectA.duration, it would not be desirable to create an instance. Also, I'd prefer not to have an instance variable since in reality it's these classes are Unity3D Monobehaviours, and it wouldn't make much sense to have a static instance since there are many being created and destroyed at various points.
What is the ideal work around if I want to be able to share the code in boo and still have access to the static duration for each derived class.
Here's a modified version of the relevant portion of the current code:
public abstract class Effect : MonoBehaviour
{
public virtual float kDuration { get { return 1.0f; }}
public float elapsed = 0.0f;
// Use this for initialization
protected virtual void Start()
{
elapsed = kDuration;
}
// Update is called once per frame
protected virtual void FixedUpdate()
{
elapsed -= Time.fixedDeltaTime;
if(elapsed <= 0) {
Destroy(this);
}
_doEffect();
}
protected abstract void _doEffect();
}
public class EffectA : Effect
{
public override float kDuration { get {return 3.0f; } }
protected override void _doEffect()
{
//Some behavior
}
}
The problem with this code is there's no static way to access kDuration for an Effect, and there are many portions in the code where I need to be able to get EffectA.kDuration or something similar without an instance.
What you're looking for is a bit strange, but one option to keep them static and provide new value/implementation is to just hide the inherited members, by simply using the same name:
public abstract class Effect
{
public const float duration = 1.0f;
public static void boo()
{
// this prints 1.0f
Console.WriteLine(duration);
}
}
public class EffectA : Effect
{
public new const float duration = 3.0f;
public new static void boo()
{
// this prints 3.0f
Console.WriteLine(duration);
}
}
Note the new keyword just gets rid of the compiler warning for you, using the same name is what results in hiding.
Update
Based on your comment, here's how you can avoid duplication and just call the shared implementation:
public abstract class Effect
{
public const float duration = 1.0f;
public static void boo(float val = duration)
{
// your complex shared implementation
Console.WriteLine(val);
}
}
public class EffectA : Effect
{
public new const float duration = 3.0f;
public new static void boo()
{
Effect.boo(duration);
}
}
Could try this but may not be the right approach:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(" duration from Effect " + Effect.duration);
Console.WriteLine(" duration from EffectA " + EffectA.duration);
Console.WriteLine(" duration from EffectB " + EffectB.duration);
Console.Read();
}
}
class Effect
{
public const float duration = 1.0f;
}
class EffectA : Effect
{
public const float duration = 3.0f;
}
class EffectB : Effect
{
}
The result should be :
duration from Effect 1
duration from EffectA 3
duration from EffectB 1
There will be a warning in Visual Studio 2015 but can be by passed.
Not sure whether can work with Unity3D MonoDevelop.

Integer gets automatically set to 0 C#

I am doing an exercise on making a small console program which shows how fast a car is moving and a function to make it go either faster or slower.
So here is my class called car, it contains a constructor.
There is a get and set accessor for the private int speed.
There are 2 methods called accelerate and break.
class car
{
private int speed;
public car (int initialSpeed) //initializes car speed
{
Speed = initialSpeed;
}
public void accelerate() //increase Speed
{
Speed = Speed + 10;
}
public void brake() //decrease Speed
{
Speed = Speed - 10;
}
public int Speed //access private int speed
{
get { return speed; }
set { speed = Speed; }
}
}
Now here is the problem:
class program
{
static void Main(string[] args)
{
var Car = new car(5);
Console.WriteLine(Car.Speed);
}
}
When I run the program the console just displays 0 even though initialized with 5. Why is this happening and what am I doing wrong?
Your Speed property is the problem. Here's the code:
public int Speed //access private int speed
{
get { return speed; }
set { speed = Speed; }
}
The getter is fine - it returns the value of the private variable.
The setter, however, sets the value of variable to the result of evaluating the getter - ignoring the value passed into the setter entirely (available via the value variable). It should be:
public int Speed
{
get { return speed; }
set { speed = value; }
}
Or better yet, use an automatically implemented property - remove the speed field, and just have:
public int Speed { get; set; }
At the same time, I'd suggest learning about compound assignment operators and .NET naming conventions. If you're using C# 6 you can also use expression-bodied members, leaving a really small amount of code:
class Car
{
public int Speed { get; set; }
public Car(int initialSpeed)
{
Speed = initialSpeed;
}
public void Accelerate() => Speed += 10;
public void Brake() => Speed -= 10;
}
Change this code:
public int Speed //access private int speed
{
get { return speed; }
set { speed = Speed; }
}
to
public int Speed //access private int speed
{
get { return speed; }
set { speed = value; }
}
In C# properties, the setter uses the value keyword to set values to the underlying field.
Your set assessor should be
set { speed = value; }
So your property definition becomes
public int Speed //access private int speed
{
get { return speed; }
set { speed = value; }
}
The problem is in the set, change this
set { speed = Speed; }
for this
set { speed = value; }
Good luck!
#Jay is correct but the preferred syntax in this case is
public int Speed { get; set;}
and remove
private int speed;
Let the compiler handle the member details for you since you are not running any actual logic in the get/set properties­­­­

Float enum and aggregate class

I have to create walet class, where i count how many coins it has, so:
enum Coins {
OneCent = 0.01f,
FiveCent = 0.05f,
OneDollar = 1.0f
}
and:
public class RowQuantity<T> {
public T entity;
public int Quantity;
}
and my walet:
public class Walet {
public List<RowQuantity<Coins>> CoinsCash;
public Walet() {
this.CoinsCash.Add(new RowQuantity<Coins> { entity = Coins.OneCent, Quantity = 25 });
}
}
The problem goes here:
I can't have enum with float value => so, i have to declare it as a static class.
public static class Coins {
public const float OneCent = 0.01f;
public const float FiveCent = 0.05f;
public const float OneDollar = 1.0f;
}
But in this way, i can't pass static type as instance of generic class.
So, how could i realise this? (List with quantity of float enum values)
First of all, to avoid rounding issues, you need to use decimal. Secondly, you need to make it an instance class that shows some static properties that are OneCent, FiveCent and OneDollar, like so:
public sealed class Coins
{
private decimal _num;
private Coins(decimal num)
{
_num = num;
}
public static readonly Coins OneCent = new Coins(0.01M);
public static readonly Coins FiveCent = new Coins(0.05M);
public static readonly Coins OneDollar = new Coins(1M);
//add more properties like this
}

Categories

Resources