I have a bunch of constant values for several types of "buildings", the sizes of which are fixed (due to the 3D model they will hold).
I've looked around and read about base classes, interfaces and abstracts, but couldn't really grasp the concepts completely. However I really liked the idea of using interfaces to "organize" classes with common fields. In this case, sizeX and sizeY is a type of field shared across all building classes.
public static class BuildingProperties {
public class House
{
public const int sizeX = 4;
public const int sizeY = 4;
}
public class House1
{
public const int sizeX = 6;
public const int sizeY = 6;
}
public class Commercial
{
public const int sizeX = 10;
public const int sizeY = 10;
}
}
Is there some way I can implement an interface for this, without the need for constructors in each class? (I would like to simply call for these constants as required, like so:)
public void program()
{
int sizeX = BuildingProperties.House.sizeX;
}
And for future use, if I needed to add another field (for example "height"), I would like the compiler to throw an error and say "hey! you forgot to give House1 a "height" value!
Is there something like this that someone can point me towards?
Seems to me like your code need some re-design. I don't see why you would want to have all these public sub classes. Instead, I would just use one class for all building types (assuming the all always have the same properties) and 3 properties for that class's type:
public class Building
{
public Building(int sizeX, int sizeY)
{
SizeX = sizeX;
SizeY = sizeY;
}
public int SizeX { get; }
public int SizeY { get; }
}
public static class BuildingProperties
{
public static Building House { get; } = new Building(4, 4);
public static Building House1 { get; } = new Building(6, 6);
public static Building Commercial { get; } = new Building(10, 10);
}
Note that all the properties are immutable in this code sample, and also, if you add a property in the future, and would like to get compiler errors when it's missing, all you have to do is change the constructor of the Building class to acccept another parameter for this new readonly property.
You can simply create an interface that will declare 2 getter properties:
public interface IProvideSizes
{
int SizeX { get; }
int SizeY { get; }
}
And in your classes have them return the data from your const:
public class House : IProvideSizes
{
public const int _sizeX = 4;
public const int _sizeY = 4;
public int SizeX { get { return _sizeX; } }
public int SizeY { get { return _sizeY; } }
}
public class House1 : IProvideSizes
{
public const int _sizeX = 6;
public const int _sizeY = 6;
public int SizeX { get { return _sizeX; } }
public int SizeY { get { return _sizeY; } }
}
public class Commercial : IProvideSizes
{
public const int _sizeX = 10;
public const int _sizeY = 10;
public int SizeX { get { return _sizeX; } }
public int SizeY { get { return _sizeY; } }
}
This way you can preserve and maintain the contract of each type, while still being able to access each type's specific size in a static way (without the need to instantiate it).
Have you considered a dictionary?
Dictionary<string, System.Drawing.Point> properties = new Dictionary<string, System.Drawing.Point>() {
{"House", new System.Drawing.Point(4,4)},
{"House1", new System.Drawing.Point(6,6)},
{"Commercial", new System.Drawing.Point(10,10)}
};
Related
In the code example below, if HighValue and LowValue properties are not set by the client, how can I pass default values for these properties to the base class?
If there is a design mistake in this example setup, I'd like to thank you in advance for warning me.
public class Foo
{
public Foo(int scaleHigh, int scaleLow)
{
ScaleHigh = scaleHigh;
ScaleLow = scaleLow;
}
public int ScaleHigh { get; }
public int ScaleLow { get; }
}
public class Bar : Foo
{
public Bar(Bar bar)
: base(bar.ScaleHigh, bar.ScaleLow)
{
HighValue = SomeHelper.ReCalculate(bar.HighValue);
LowValue = SomeHelper.ReCalculate(bar.LowValue);
}
public int HighValue { get; }
public int LowValue { get; }
}
public class SomeHelper
{
public static int ReCalculate(int scale)
{
return scale * 5;
}
}
public class Client : Bar
{
public Client(Bar bar) : base(bar) { }
public int Request(bool condition)
{
return condition ? HighValue : LowValue;
}
}
you have a bug in your bar class, since it doesn't have a default constructor, you will never be able to create the object, since it will be a recursion forever - each new instance would neeed another and so on
public class Bar : Foo
{
public Bar(Bar bar)
: base(bar.ScaleHigh, bar.ScaleLow)
{
HighValue = SomeHelper.ReCalculate(bar.HighValue);
LowValue = SomeHelper.ReCalculate(bar.LowValue);
}
public int HighValue { get; }
public int LowValue { get; }
}
you can fix it by adding another constructor like this
public Bar(int scaleHigh=0, int scaleLow=0, int highValue=0, int lowValue=0)
: base(scaleHigh, scaleLow)
{
HighValue = SomeHelper.ReCalculate(highValue);
LowValue = SomeHelper.ReCalculate(lowValue);
}
Try this:
public int LowValue { get; } = 0; //You can change these values.
public int HighValue { get; } = 10;
Sorry if I misunderstand, but I believe you want to set default values of Bar if they are not set? In what case would the constructor not set the values?
In the case that you didn't set those in your constructor, one thing you can consider is making the types int? and then set the variable like this:
public int? HighValue => HighValue ?? (defaultValue)
This question already has answers here:
What's the correct alternative to static method inheritance?
(8 answers)
How to use polymorphism or inheritance in static classes?
(4 answers)
Closed 2 years ago.
I have a static class containing several subclasses for managing different constants.
Very different classes I want to implement the same properties depending only on the defined constants.
It looks like this:
public static class A
{
public static class Subclass1
{
public const int Constant1 = 0;
public const int Constant2 = 1;
public static List<int> Elements
{ get { return new List<int> { Constant1, Constant2 }} }
public static int Sum { get { return Elements.Sum(); } }
public static int NegSum { get { return -Elements.Sum(); } }
}
public static class Subclass2
{
public const int Constant3 = 3;
public const int Constant4 = 4;
public static List<int> Elements
{ get { return new List<int> { Constant3, Constant4 }} }
public static int Sum { get { return Elements.Sum(); } }
public static int NegSum { get { return -Elements.Sum(); } }
}
}
so that I can easily access them by
int a = A.Subclass1.Constant1;
List<int> b = A.Subclass1.Elements;
int c = A.Subclass1.Sum;
The code of the Properties Sum and NegSum is always the same.
You see the problem: I need to include them for every subclass again. Is there any way to reuse the code of the properties without implementing them for every single class?
What I would like to do is something like:
public abstract class Base
{
public abstract static List<int> Elements { get; }
public static int Sum { get { return Elements.Sum(); } }
public static int NegSum { get { return -Elements.Sum(); } }
}
public static class B
{
public static class Subclass1 : Base
{
const int Constant1 = 0;
const int Constant2 = 1;
public override static List<int> Elements
{ get { return new List<int> { Constant1, Constant2 }} }
}
public class Subclass2 : Base
{
const int Constant3 = 0;
const int Constant4 = 1;
public override static List<int> Elements
{ get { return new List<int> { Constant3, Constant4 }} }
}
}
Well, I know that in C# Inheritance like this doesn't work for static classes.
Is there any other smart way to implement this?
Maybe try implementing Subclass1 and Subclass2 without static keyword. Like this
public abstract class Base
{
public Base(params int[] elements)
{
this.Elements = new List<int>(elements);
}
public List<int> Elements { get; private set; }
public virtual int Sum { get { return Elements.Sum(); } }
public virtual int NegSum { get { return -Elements.Sum(); } }
}
public static class B
{
public static class Subclass1 : Base
{
const int Constant1 = 0;
const int Constant2 = 1;
public Subclass1() : base(Constant1, Constant2){}
}
public class Subclass2 : Base
{
const int Constant3 = 0;
const int Constant4 = 1;
public Subclass2() : base(Constant3, Constant4){}
}
}
Then add two static properties to class B
public static Subclass1 InstanceSubclass1 {get; private set}
public static Subclass2 InstanceSubclass2 {get; private set}
At the end add static constructor to class B
static B()
{
InstanceSubclass1 = new Subclass1 ();
InstanceSubclass2 = new Subclass2 ();
}
You can now access to your classes by using
B.InstanceSubclass1
What you are wanting will not be possible without some code duplication. C# doesn't handle inheritance with static the same way. While you can't override the static member of a super class, you can use new to hide and reimplement it. The downside to this is you lose the subtype contract that abstract provides, but if you really want your types to be "abstract" and have static members, you are pretty much SOL on that front.
public class Base
{
public static List<int> Elements { get; }
public static int Sum(List<int> Elements) => Elements.Sum();
public static int NegSum(List<int> Elements) => -Elements.Sum();
}
public static class B
{
public sealed class Subclass1 : Base
{
const int Constant1 = 1;
const int Constant2 = 2;
public static new List<int> Elements
{ get => new List<int> { Constant1, Constant2 }; }
public static new int Sum { get => Base.Sum(Elements); }
public static new int NegSum { get => Base.NegSum(Elements); }
}
public sealed class Subclass2 : Base
{
const int Constant3 = 3;
const int Constant4 = 4;
public static new List<int> Elements
{ get => new List<int> { Constant3, Constant4 }; }
public static new int Sum { get => Base.Sum(Elements); }
public static new int NegSum { get => Base.NegSum(Elements); }
}
}
An alternative is that you can use the singleton pattern to create the illusion that you are achieving what you want to achieve. As far as intellisense is concerned, this will produce the exact same effect of accessing the members like B.Subclass1.Sum. The downside being that this would also expose the _Subclass1 and _Subclass2 classes and pollute the namespace, but you will just have to decide if that is an acceptable trade-off.
public abstract class Base
{
public abstract List<int> Elements { get; }
public int Sum { get => Elements.Sum(); }
public int NegSum { get => -Elements.Sum(); }
}
public static class B
{
public static _Subclass1 Subclass1 { get; } = new _Subclass1();
public static _Subclass2 Subclass2 { get; } = new _Subclass2();
public sealed class _Subclass1 : Base
{
const int Constant1 = 1;
const int Constant2 = 2;
public override List<int> Elements
{ get => new List<int> { Constant1, Constant2 }; }
}
public sealed class _Subclass2 : Base
{
const int Constant3 = 3;
const int Constant4 = 4;
public override List<int> Elements
{ get => new List<int> { Constant3, Constant4 }; }
}
}
You could use interfaces and an extension method if you didn't want to have a base class:
public interface IElementsHost
{
List<int> Elements { get; }
}
public static class ElementsExtensions
{
public static int Sum(this IElementsHost host) => host.Elements.Sum();
public static int NegSum(this IElementsHost host) => -host.Elements.Sum();
}
public class Host : IElementsHost
{
public const int Constant1 = 2;
public const int Constant2 = 3;
public List<int> Elements { get; }
= new List<int>(new int[]{ Constant1, Constant2 });
}
// client code
var host = new Host();
var sum = host.Sum();
If you wanted related subclasses to have such capabilities, you'd have to do it with composition. It would look like:
public static class OtherStaticClass
{
public static ElementHost { get; } = new Host();
static OtherStaticClass()
{
Host.Elements.Add(/* some constant, etc. */);
}
}
// client code
var sum = OtherStaticClass.ElementHost.Sum();
I was trying to illustrate the Liskov principle with a case where it breaks it and was expecting in the below example that when you set breadth for the sqaure, the length is automatically set to the same length, and vice versa.
However, the area is returned as 0. I was expecting 4x4=16, and 5x5=25, in the second case. What am I doing wrong? I suspect it's in the way I'm overriding the properties of the base class.
using System;
public class Rectangle
{
public int length { get; set; }
public int breadth { get; set; }
public int area()
{
return length * breadth;
}
}
public class Square : Rectangle {
public new int length;
public new int breadth;
public new int Length
{
get
{
return this.length;
}
set
{
this.breadth = this.length = value;
}
}
public new int Breadth
{
get
{
return this.breadth;
}
set
{
this.breadth = this.length = value;
}
}
}
public class Program
{
public static void Main()
{
Square s = new Square();
s.length = 4;
s.breadth = 5;
int xx = s.area();
Console.Write(xx);
s.length = 5;
s.breadth = 4;
xx = s.area();
Console.Write(xx);
}
}
When you inherit from a base class, you will inherit all of its Public and Protected members. When you declare a new member in the derived class with the same name. The compiler will gives you a warning asking you are you intended to hide that member? When you used the new keyword you told the compiler: Yes I want to hide this member please. The implementation of the area Method uses the base class properties, so it will not see your public Fields That's why you get the 0.
So your code will become:
public class Rectangle
{
protected int _length;
protected int _breadth;
public virtual int Length
{
get { return _length; }
set { _length = value; }
}
public virtual int Breadth {
get { return _breadth; }
set { _breadth = value; }
}
public int Area()
{
return Length * Breadth;
}
}
public class Square : Rectangle
{
public override int Breadth
{
get { return _breadth; }
set { _breadth = value;
_length = _breadth;
}
}
public override int Length {
get { return _length; }
set { _length = value;
_breadth = _length;
}
}
}
If you want to override something, you should add the virtual keyword in the base class definition of that thing.
In your example, you will cause a StackOverFlow exception. Because each property setters will call the other. That's why I used a protected member to prevent this thing from happening.
This is a good reference for you to read about inheritance
is there a way to put these into either a 1 D array or a 2 D array. ? i have produced code and it looks a bit untidy as well as long can this be shortened?
double worstPrice = 6.47;
double bestPrice = 0.99;
double CivetCatPrice =29.14;
double whenPrice = 10.50;
double everythingPrice = 319.56;
int bestStock = 3238;
int worstStock = 8;
int civetCatstock = 3;
int whenStock = 37;
int everythingStock = 2;
You can make an array for each doubles and ints like this
double[] priceData = new double[]{ 6.47, 0.99, 29.14, 10.50, 319.56 };
int[] stockData = new int[]{ 3238, 8, 3, 37, 2 };
Alternatively you can use a dictionary if you wish for them to keep their names
Dictionary<string, double> priceDict = new Dictionary<string, double>();
priceDict.Add("worstPrice", 6.47);
//And so on for each double
Dictionary<string, int> stockDict = new Dictionary<string, int>();
priceDict.Add("bestStock", 3238);
//And so on for each int
The values in these can be called like so
double worstMinusBestPrices = priceData[0] - priceData[1]; //For arrays
double worstMinusBestPrices = priceDict["worstPrice"] - priceDict["bestPrice"] //For dictionaries
You could implement a custom class which holds these values as proprties with meaningful names. Then your code will be much more readable, maintainable and robust.
For example (you don't need all of these classes, it should just give you an idea):
public abstract class Animal
{
public Animal(string animalName)
{
this.Name = animalName;
}
//insert properties and methods which all aimals share here
public string Name { get; set; }
}
public class CibetCat : Animal
{
public CibetCat() : base("CibetCat")
{
}
//insert properties and methods which all CibetCats share here
}
Now your class that holds the price and stock informations as well as the reference to the animal itself(CibetCat in your example):
public class AnimalStock // or AnimalPrice or whatever
{
public AnimalStock(Animal animal)
{
this.Animal = animal;
}
public AnimalStock(Animal animal, decimal worstPrice, decimal bestPrice, int bestStock, int worstStock)
{
this.Animal = animal;
this.Worstprice = worstPrice;
this.BestPrice = bestPrice;
this.BestStock = bestStock;
this.WorstStock = worstStock;
}
public Animal Animal { get; set; }
public decimal Worstprice { get; set; }
public decimal BestPrice { get; set; }
public int BestStock { get; set; }
public int WorstStock { get; set; }
// ...
}
Lot of code but not complex. Now You can write this simple and readable code:
Animal cibetCat = new CibetCat();
AnimalStock stock = new AnimalStock(cibetCat);
stock.BestPrice = 0.99m;
stock.Worstprice = 6.47m;
stock.BestStock = 3238;
// ...
Later you can access all these properties(or it's methods) from a single instance.
Console.WriteLine("Animal's best-price is: {0}", stock.BestPrice); // etc
As Alfie pointed out, you could use a dictionary - but you're then referencing things by a string identifier, that you have to remember.
Another way would be to use a class or struct. There are of course many ways to do this, but some include:
public class Things
{
public double worstPrice = 6.47;
public double bestPrice = 0.99;
public double CivetCatPrice =29.14;
public double whenPrice = 10.50;
public double everythingPrice = 319.56;
public int bestStock = 3238;
public int worstStock = 8;
public int civetCatstock = 3;
public int whenStock = 37;
public int everythingStock = 2;
}
Another way would be:
public class Things
{
public double WorstPrice { get; readonly set; }
public double BestPrice = { get; readonly set; }
// etc
public Things(double worstPrice, double bestPrice) // etc
{
WorstPrice = worstPrice;
BestPrice = bestPrice;
}
}
There are pros and cons to both approaches. Another potential is to use a collection of a class/struct to group things and aggregate them in meaningful ways.
Like:
public class Thing
{
public string ThingLabel { get; readonly set; }
public double ThingPrice { get; readonly set; }
public int ThingQuantity { get; readonly set; }
// the value of your stock, calculated automatically based on other properties
public double ThingValue { get { ThingPrice * ThingQuantity; } }
public Thing(string thingLabel, double thingPrice, int thingQuantity)
{
ThingLabel = thingLabel;
// etc
}
}
public void DoStuff()
{
List<Thing> list = new List<Thing>();
Thing thing = new Thing("Civet cat", 500, 10);
list.Add(thing);
list.Add(new Thing("Sea flap flap", 100, 5);
list.Add(new Thing("Nope Rope", 25, 4);
Console.WriteLine("The value of {0}'s stock is: {1}", thing.ThingLabel, thing.Value);
}
and yet another way is to use a base class and create sub classes of your different types. The possibilities are nearly endless! You just have to decide which way works best for you now, you later, and your potential team.
I want to access to static fields of a type, which is a class, introduced in a generic function. But compiler always gives me this error
'T' is a 'type parameter', which is
not valid in the given context
here is the code.
public class A
{
public static int Num = 1;
public int GetClassNum<T>() where T : A
{
//return T.Num;
//return default(T).Num;
//return what???
}
}
public class B : A
{
public static int Num = 2;
}
public class C : A
{
public static int Num = 3;
}
I suspect that this has something to do with the fact that interfaces are generally used to filter the typename in a generic function. or must it be always? In this case there should not be a static field. Is there any way I can achieve?
try this:
public class A
{
private static int _num = 1;
public virtual int Num { get { return _num; } set { _num = value; } }
public int GetClassNum<T>(T input) where T : A
{
return input.Num;
}
}
Then override Num in the derived classes
What you are doing is wrong, you are trying to access a type, not an instance.
So how to resolve this,
public class A
{
public static int Num = 1;
public int GetClassNum<T>(T inn) where T : A
{
inn.Num //really
}
}
wait, wait... You cant do this too. Because Num is static and what we have passed (T inn) is a object reference(Only a class can access static fields, not objects).Then how can we make this work. One way is to make T as a static type, so
public static class A
{
public static int Num = 1;
public int GetClassNum<T>(T inn) where T : A // Error here
{
inn. /// no Num
}
}
wait, you cant do this too. Because you cannot use static instances as generic constraint because static is sealed itself.
So How to access Num, change Num to object instance or refer Preets answer for other option.
Static fields belong to type, not instance of the type. You cannot refer to the static elements of the type parameter because they are not inherited.
Make Num not static property:
public class A
{
public virtual int Num
{
get { return 1; }
}
public int GetClassNum<T>(T instance) where T : A
{
return instance.Num;
}
}
public class B : A
{
public override int Num
{
get { return 2; }
}
}
public class C : A
{
public override int Num
{
get { return 3; }
}
}