I have a base class that does calculations on image sizes. I'm deriving a class from that and have predefined image sizes that will be used in my code. While what I have works, I have a strong feeling that I'm not doing it properly.
Ideally, I'd like to just pass DerviedClass.PreviewSize as the parameter to GetWidth without having to create an instance of it.
class Program
{
static void Main(string[] args)
{
ProfilePics d = new ProfilePics();
Guid UserId = Guid.NewGuid();
ProfilePics.Preview PreviewSize = new ProfilePics.Preview();
d.Save(UserId, PreviewSize);
}
}
class ProfilePicsBase
{
public interface ISize
{
int Width { get; }
int Height { get; }
}
public void Save(Guid UserId, ISize Size)
{
string PicPath = GetTempPath(UserId);
Media.ResizeImage(PicPath, Size.Width, Size.Height);
}
}
class ProfilePics : ProfilePicsBase
{
public class Preview : ISize
{
public int Width { get { return 200; } }
public int Height { get { return 160; } }
}
}
It seems to me that you want a more flexible implementation of ISize - having an implementation which always returns the same value seems fairly pointless. On the other hand, I can see that you want an easy way of getting the size that you always use for a preview. I would do it like this:
// Immutable implementation of ISize
public class FixedSize : ISize
{
public static readonly FixedSize Preview = new FixedSize(200, 160);
private readonly int width;
private readonly int height;
public int Width { get { return width; } }
public int Height { get { return height; } }
public FixedSize(int width, int height)
{
this.width = width;
this.height = height;
}
}
You could then write:
ProfilePics d = new ProfilePics();
Guid userId = Guid.NewGuid();
d.Save(userId, FixedSize.Preview);
This would reuse the same instance of FixedSize whenever you called it.
There are a few ways that you could do this, depending on your needs. I would look at doing a different interface, setup. Something like this.
public interface ISizedPics
{
int Width {get; }
int Height {get; }
void Save(Guid userId)
}
public class ProfilePics, iSizedPics
{
public int Width { get { return 200; } }
public int Height { get { return 160; } }
public void Save(Guid UserId)
{
//Do your save here
}
}
Then, with this done, you could actually work with it like this.
ISizedPics picInstance = new ProfilePics;
Guid myId = Guid.NewGuid();
picInstance.Save(myId);
This is just one way of doing it, I like this way, as you can easily create a factory class around this that helps you declare the instances as needed.
Related
I have written the code below, but i see that for to access the width and the length for the last child which is badRectangle is by overriding everything inhrerited from the Rectangle and shape class, which means i have to duplicate the input and i i had 6 or more levels of inheritance the code would kind of confuse and repeat a lot of things.
This code works correctly but is the correct way of dealing with inheritance in C#.
class Program
{
static void Main(string[] args)
{
badRectangle myRect = new badRectangle(true,"Rectangle",23.0,23);
Console.WriteLine("The Area of your Rectangle = " + myRect.getArea().ToString()
+ "\nAnd " + myRect.getStatus());
Console.ReadLine();
}
public abstract class shape
{
string type;
public abstract double getArea();
public shape(string type)
{
this.type = type;
}
}
public class rectangle : shape
{
double width, length;
public rectangle(string type, double width, double length):base(type)
{
this.width = width;
this.length = length;
}
public override double getArea()
{
return width * length;
}
}
public class badRectangle : rectangle
{
double width, length;
bool badOrNot = false;
public badRectangle(bool badOrNot,string type, double width, double length):base(type,width,length)
{
this.badOrNot = badOrNot;
this.width = width;
this.length = length;
}
public string getStatus()
{
string answer = "No, Rectangle is not bad";
if (badOrNot == true)
{
answer = "Yes, Rectangle is bad";
}
return answer;
}
public override double getArea()
{
return width * length;
}
}
}
This would be the "correct" or conventional way to do this in C#:
public abstract class Shape
{
public string Type { get; private set; }
public abstract double Area { get; }
public Shape(string type)
{
this.Type = type;
}
}
public class Rectangle : Shape
{
public double Length { get; private set; }
public double Width { get; private set; }
public Rectangle(string type, double width, double length)
: base(type)
{
this.Width = width;
this.Length = length;
}
public override double Area { get { return this.Width * this.Length; } }
}
public class BadRectangle : Rectangle
{
public bool BadOrNot { get; private set; } = false;
public BadRectangle(string type, double width, double length, bool badOrNot)
: base(type, width, length)
{
this.BadOrNot = badOrNot;
}
public string Status
{
get
{
string answer = "No, Rectangle is not bad";
if (this.BadOrNot == true)
{
answer = "Yes, Rectangle is bad";
}
return answer;
}
}
}
You don't need to set width and length in the derived classes again, just pass them to the constructor of the base class. If you need to access them in the derived class, make them protected. The getArea() doesn't have to be overridden if it does the same thing.
I want to create configuration for my application using static classes.
Firstly please forgive my ignorance, I'm not a full time c# dev. I come from a Ruby/Javascript world where dynamic access to constants & variables is trivial.
Whether or not this is the right approach here I'm not 100% at the moment. Would be greatful of other suggested approaches.
I have the following static class setup for my config:
public static class Config
{
public static class MaterialQuality
{
public static class Low
{
public const float Value = 0.1f;
public const int Cost = 10;
}
public static class Medium
{
public const float Value = 0.2f;
public const int Cost = 20;
}
public static class High
{
public const float Value = 0.2f;
public const int Cost = 40;
}
}
}
I then have a class Material, which is passed an enum value relating to the aboves types Low,Medium,High.
The reason for the enum in unity this gives a quick way for devs to provide level designers with an option list for a an object.
So by choosing an enum value the level designer can set the properties stored in the config without actually having to enter the values directly onto the object. The values are set against the object when it is initialised.
In the constructor I want to set member variables for Cost & Value from the static config values for the MaterialQuality enum value passed.
public enum MaterialQuality
{
Low,Medium,High
}
public class Material
{
private int Cost;
private float Value;
Material(MaterialQuality quality) {
Cost = Config.MaterialQuality.<quality>.Cost;
Value = Config.MaterialQuality.<quality>.Value;
//in Javascript I'd use associative array access to the object
Cost = Config.MaterialQuality[quality].Cost;
//in Ruby we have const_get() on classes.
Cost = Config.MaterialQuality.const_get(quality).Cost
}
}
The main reason for this approach is to provide single place for configuration & provide a fairly simple way for a non technical person to make changes to parts of the application without having to delve into the main classes. Also it allows me to take advantage of the constants being available in intellisense.
I'm a fan of using dictionaries for this type of configuration.
void Main()
{
var config = Config.Qualities[MaterialQualities.Low];
var cost = config.Cost;
var value = config.Value;
}
public static class Config
{
public static Dictionary<MaterialQualities, MaterialQuality> Qualities =
new Dictionary<MaterialQualities, MaterialQuality>
{
{ MaterialQualities.Low, new MaterialQuality { Value = 0.1F, Cost = 10 }},
{ MaterialQualities.Medium, new MaterialQuality { Value = 0.2F, Cost = 20 }},
{ MaterialQualities.High, new MaterialQuality { Value = 0.2F, Cost = 40 }},
};
}
public class MaterialQuality
{
public float Value { get; set; }
public int Cost { get; set; }
}
public enum MaterialQualities
{
Low, Medium, High
}
Probably better approach would be:
public static class Config
{
public class Material
{
public Material(float value, int cost){
Value = value;
Cost = cost;
}
public float Value {get; private set;}
public int Cost {get; private set;}
public Material GetFor(MaterialQuality quality){
switch(quality){
case MaterialQuality.Low: return new Material(0.1f, 10);
case MaterialQuality.Medium: return new Material(0.2f, 20);
case MaterialQuality.High: return new Material(0.2f, 40);
}
throw new Exception("Unknown material quality " + quality);
}
}
}
and later you can use that:
//....
Material materialData = Material.GetFor(quality);
Cost = materialData.Cost;
Value = materialData.Value;
//...
I would use a struct and static properties in MaterialQuantity instead of an enum. Something like the following:
public struct MaterialQualityInfo
{
public MaterialQualityInfo( float value, int cost )
{
Value = value;
Cost = cost;
}
public float Value { get; private set; }
public int Cost { get; private set; }
}
public static class Config
{
public static class MaterialQuality
{
public static MaterialQualityInfo Low
{
get { return new MaterialQualityInfo( 0.1f, 10 ); }
}
public static MaterialQualityInfo Medium
{
get { return new MaterialQualityInfo( 0.2f, 20 ); }
}
public static MaterialQualityInfo High
{
get { return new MaterialQualityInfo( 0.2f, 40 ); }
}
}
}
public class Material
{
private int Cost;
private float Value;
Material( MaterialQualityInfo quality )
{
Cost = quality.Cost;
Value = quality.Value;
}
}
IMHO, this isn't a good usage of static classes. You should use regular object-oriented programming to solve the issue.
I see that all material qualities have 2 properties in common: Value and Cost. For me, this means that you should design a class called MaterialQuality:
public class MaterialQuality
{
public float Value { get; set; }
public int Cost { get; set; }
}
If material qualities are part of an application configuration, I see that you should design a Configuration class as follows:
public class Configuration
{
public List<MaterialQuality> MaterialQualities { get; } = new List<MaterialQuality>();
}
...and if you want to initialize a configuration per application life-cycle, you can improve Configuration class using static field initializers:
public class Configuration
{
private readonly static Configuration _current = new Configuration();
public static Configuration Current => _current;
public List<MaterialQuality> MaterialQualities { get; } = new List<MaterialQuality>();
}
Now adding new material qualities to current configuration is as easy as the following code:
Configuration.Current.MaterialQualities.Add(new MaterialQualities { Value = 0.1f, Cost = 10 });
If you want to provide a fluent API to add material qualities is also easy: we're going to turn public MaterialQualities properties into an ImmutableList<T> (so you force developers to add materials using the method to do so) and add an AddMaterial method:
public class Configuration
{
private readonly static Configuration _current = new Configuration();
private readonly List<MaterialQuality> _materialQualities = new List<MaterialQuality>();
public static Configuration Current => _current;
public IImmutableList<MaterialQuality> MaterialQualities => _materialQualities.ToImmutableList();
public Configuration AddMaterial(float value, int cost)
{
_materialQualities.Add(new MaterialQuality { Value = value, Cost = cost });
return this;
}
}
...and now adding many materials would look even nicer!
Configuration.Current.AddMaterial(0.1f, 10)
.AddMaterial(0.2f, 20)
.AddMaterial(0.2f, 40);
How about:
public enum MaterialQuality
{
Low, Medium, High
}
public class Material
{
private int Cost;
private float Value;
private readonly Dictionary<MaterialQuality, Tuple<int, float>> storageMap = new Dictionary<MaterialQuality, Tuple<int, float>>
{
{ MaterialQuality.Low, Tuple.Create(10, 0.1f)},
{ MaterialQuality.Low, Tuple.Create(20, 0.2f)},
{ MaterialQuality.Low, Tuple.Create(40, 0.2f)},
};
public Material(MaterialQuality quality)
{
Cost = storageMap[quality].Item1;
Value = storageMap[quality].Item2;
}
}
If you are not using your enum widely, you could do something like:
public class Material
{
public float Value { get; private set; }
public int Cost { get; private set; }
public Material(float value, int cost)
{
Value = value;
Cost = cost;
}
public static Material Low { get { return new Material(0.1f, 10); } }
public static Material Medium { get { return new Material(0.2f, 20); } }
public static Material High { get { return new Material(0.2f, 40); } }
}
And then:
var myLowMaterial = Material.Low;
var myMediumMaterial = Material.Medium;
var myHighMaterial = Material.High;
Unless you are using your enum for something, in which case you could add:
public static Material Get(MaterialQuality quality)
{
switch(quality)
{
case MaterialQuality.Low:
return Low;
case MaterialQuality.Medium:
return Medium;
case MaterialQuality.High:
return High;
}
throw new Exception("We should never go here");
}
I was doing some reading here about creating immutable object in java and I was wondering, is it okay to create a mutable object in certain situations?
For example, let's say we were creating a ping-pong game in C#, obviously, we would have a class that represents a ball, and the two paddles, would you write the ball class like this:
class Ball
{
private readonly int xPosition;
private readonly int yPosition;
private readonly int ballSize;
private readonly string ballColor;
public Ball(int x, int y, int size, string color)
{
this.xPosition=x;
this.yPosition=y;
this.ballSize = size;
this.ballColor = color;
}
public int getX
{
get
{
return this.xPosition;
}
}
//left out rest of implementation.
or like this:
class Ball
{
private int xPosition;
private int yPosition;
private int ballSize;
private string ballColor;
public Ball(int x, int y, int size, string color)
{
this.xPosition=x;
this.yPosition=y;
this.ballSize = size;
this.ballColor = color;
}
public int getX
{
get
{
return this.xPosition;
}
set
{
this.xPosition = value;
}
}
}
}
In a situation where our object(ball) can change position, size(smaller or larger depending on level) and color, wouldn't it be better to provide a setter property? In this case making it mutable makes sense? How would you approach this?
If you are using c#, you do not need to go thru the overhead of creating separate fields to make objects immutable. Instead you can do something like this -
class Ball
{
public Ball ( int x, int y, int size, string color)
{ ... }
public int XPos {get; private set; }
public int YPos {get; private set; }
public int Size {get; private set; }
public string BallColor {get; private set; }
}
This way, you can still write methods in the class to mutate the properties but nothing outside of the class can change their values.
I've been working on building several classes which inherit from one base class but I'm not entirely confident on how inheritance and polymorphism work in C# at this stage.
My base class looks like this:
abstract class Structure
{
public int currentCost = 0;
public int currentArea = 0;
public int currentPopulation = 0;
public int currentConstruction = 0;
public int currentEnergy = 0;
public int currentEconomy = 0;
public abstract int baseCost { get; }
public abstract int baseEnergy { get; }
public abstract int baseEconomy { get; }
public abstract int baseConstruction { get; }
public int baseArea = -1;
public int basePopulation = -1;
public int level = 0;
public abstract string structureName { get; }
}
Now, classes that inherit from the Structure class will be made to provide their own assignments for the abstract variables which is fine as most of the classes vary wildly in the figures they assign.
The abstract variables are used in the derived classes in the following (incomplete) manner:
class BiosphereModification : Structure
{
const int baseEconomyBiosphereModification = 0;
const int baseConstructionBiosphereModification = 0;
const int baseCostBiosphereModification = 2000;
const int baseEnergyBiosphereModification = 0;
const int baseFertilityBiosphereModification = 1;
const string structureNameBiosphereModification = "BiosphereModification";
public override int baseCost { get { return baseCostBiosphereModification; } }
public override int baseEconomy { get { return baseEconomyBiosphereModification; } }
public override int baseEnergy { get { return baseEnergyBiosphereModification; } }
public override int baseConstruction { get { return baseConstructionBiosphereModification; } }
}
However, the non-abstract variables will be the same across the majority of derived classes, but not all of them.
I could make them all abstract and force each class to provide it's own value, but this seems counter-intuitive. What I would prefer is a way to provide a value in the base class and provide an override in a derived class if needed.
Is there a way to do this? I know that this can be done with methods declared virtual. This allows the derived class to use the base classes method unless it provides one of it's own. Surely a similar thing exists for this?
What I would prefer is a way to provide a value in the base class and provide an override in a derived class if needed.
Properties can be declared virtual, as well:
public virtual int BaseCost { get { return 0; } }
public virtual int BaseEnergy { get { return 42; } }
public virtual int BaseEconomy { get { return 3982; } }
public virtual int BaseConstruction { get { return 398829; } }
You can then override them when appropriate:
public override int BaseCost { get { return 2; } }
Help me with building object model, please.
I need abstract class Unit representing each military unit in a game. There is Soldier, Tank, Jet and Bunker (children of Unit). Each of them has int properties Count and Defense, constructor with single int count parameter and one method GetTotalDefense.
My idea is following.
private abstract class Unit
{
private int Count { get; set; }
private const int Defense = 0;
protected Unit(int count)
{
Count = count;
}
public int GetTotalDefense()
{
return Count * Defense;
}
}
private class Tank : Unit
{
private const int Defense = 5;
}
Each unit has different Count and different Defense. Body of constructor and body of GetTotalDefense is always the same. What I need is in child class override Defense, because each unit has different. This property should be const, all instances of Tank (Soldier, ...) has same defense. Is there a possibility to inherit const property or each child needs its own const Defense property?
And here is an example I'd like to achieve.
Oh, there is also class Troop
public class Troop
{
private Soldier Soldiers { get; set; }
private Tank Tanks { get; set; }
private Jet Jets { get; set; }
private Fort Forts { get; set; }
public Troop(int soldiers, int tanks, int jets, int forts)
{
Soldiers = new Soldier(soldiers);
Tanks = new Tank(tanks);
Jets = new Jet(jets);
Forts = new Fort(forts);
}
public int GetTotalDefense()
{
return Soldiers.GetTotalDefense() + Tanks.GetTotalDefense() + Jets.GetTotalDefense() + Forts.GetTotalDefense();
}
}
Also, feel free to suggest better solution, thanks.
PS: I'm really strict about access modifiers, so be precise in your examples, thank you.
You can't really use a const but you can make a readonly property also are you sure you want the classes to be private and not internal or public?
public abstract class Unit {
protected Unit(int count) {
Count=count;
}
protected int Count { get; private set; }
protected abstract int Defense {get;}
public int TotalDefense {
get { return Count*Defense; }
}
}
public class Tank : Unit {
public Tank(int count) : base(count) {}
protected override int Defense {
get { return 5; }
}
}
public class Troop {
private Unit[] Troops;
public Troop(int soldiers, int tanks, int jets, int forts) {
Troops = new Unit[] {
new Soldier(soldiers),
new Tank(tanks),
new Jet(jets),
new Fort(forts)
};
}
// The using System.Linq you can do
public int TotalDefense {
get { return Troops.Sum(x=>x.TotalDefense);}
}
}
Although this solution does not use const, it achieves what you want:
internal abstract class Unit
{
private int Count { get; set; }
private int Defense { get; set; }
public int TotalDefense { get { return Count * Defense; } }
protected Unit(int defense, int count)
{
Defense = defense;
Count = count;
}
}
internal class Tank : Unit
{
protected Tank(int count)
: base(5, count) // you can use a const variable instead of 5
{
}
}
Or maybe this is more suitable:
internal abstract class Unit
{
private int Count { get; set; }
public abstract int Defense { get; }
public int TotalDefense { get { return Count * Defense; } }
protected Unit(int count)
{
Count = count;
}
}
internal class Tank : Unit
{
override public int Defense { get { return 5; } }
protected Tank(int count) : base(count)
{
}
}
What you're looking for is actually readonly. Also, since Defense is used in subclasses, you need to make it protected.
private abstract class Unit
{
private int _Count;
protected readonly const int Defense;
public int TotalDefense
{ get { return Count * Defense; } }
protected Unit (int count, int defense)
{
Defense = defense;
_Count = count;
}
}
private class Tank : Unit
{
public Tank (int Count)
: base (Count, 5)
{ }
}
public class Troop
{
public IEnumerable<Unit> Units { get; protected set; }
public Troop (int soldiers, int tanks, int jets, int forts)
{
Troops = new Unit[]
{
new Soldier (soldiers),
new Tank (tanks),
new Jet (jets),
new Fort (forts)
}
}
}
maybe something like this (but this is in java)
abstract class Unit {
Unit(int defense,int count) {
this.defense = defense;
this.count=count;
}
final int defense;
int count;
}
class Soldier extends Unit {
Soldier(int count) {
super(1,count);
}
}
class Tank extends Unit {
Tank(int count) {
super(5,count);
}
}
public class Main {
public static void main(String[] args) {
Unit[] units = { new Soldier(2), new Tank(3) };
for(Unit unit:units)
System.out.println(unit.count+" "+unit.defense);
}
}