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();
Related
I have a lot of classes that are all certain to contain an int called val, which I'd like to sort them on. They look something like this:
public class KeyString
{
public string key;
public int val;
}
public class KeySprite
{
public Sprite key;
public int val;
}
public class KeyInt
{
public int key;
public int val;
}
Currently I sort them like this:
public static List<KeyString> SortKeyString(List<KeyString> l){
l.Sort((a,b) => a.val.CompareTo(b.val));
return l;
}
public static List<KeySprite> SortKeySprite(List<KeySprite> l){
l.Sort((a,b) => a.val.CompareTo(b.val));
return l;
}
public static List<KeyInt> SortKeyInt(List<KeyInt> l){
l.Sort((a,b) => a.val.CompareTo(b.val));
return l;
}
This ... works, in the sense that it gets the right answer, but to me this feels like potentially unnecessary code duplication. Is it possible to write a single sort method that could sort a list of any of these classes?
(Note: I'm only sorting lists of a single class at a time - We're not trying to combine two different classes here.)
Create a class like:
public class KeyBase
{
public int val;
}
now Inherit all your classes from it:
public class KeyString : KeyBase
{
public string key;
}
public class KeySprite : KeyBase
{
public Sprite key;
}
public class KeyInt : KeyBase
{
public int key;
}
public static List<T> SortKey<T>(List<T> l) where T: KeyBase
{
l.Sort((a,b) => a.val.CompareTo(b.val));
return l;
}
If the only different in your classes is the type of key variable, you can do something like:
public class Key<T>
{
public T key;
public int val;
}
public static List<Key<T>> Sort<T>(List<Key<T>> l)
{
l.Sort((a,b) => a.val.CompareTo(b.val));
return l;
}
var stringKeys = new List<Key<string>> { ... };
var intKeys = new List<Key<int>> { ... };
var SpriteKeys = new List<Key<Sprite>> { ... };
Demo
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)}
};
public class ImplicitTypeConstructor
{
public static int implicitInt = 10;
}
public class ExplicitTypeConstructor
{
public static int explicitInt;
static ExplicitTypeConstructor()
{
explicitInt = 10;
}
}
How do these implementations differs from each other?
Sorry for the title i will put here an example of what i want to accomplish:
namespace mdclass
{
class pClass
{
static void Main()
{
tiles<int> tl = new tiles<int>();
tl[0].X = 0;
}
}
class tiles<T> : List<T>
{
public int X
{
//get/set the X-coordonate
}
public int Y
{
//get/set the Y-coordonate
}
}
}
how can i transfer the [0] from the tl[0] in the public int X and work with it?
Create a class for x and y coordinates:
public sealed class Point {
public int X { get; set; }
public int Y { get; set; }
}
Use the Point class to store the coordinates into the list:
public sealed class Program {
public static void Main() {
var tiles = new List<Point>();
tiles.Add(new Point { X = 5, Y = 10 });
tiles[0].X = 15;
}
}
Could you not just make tl public?
Then myInt = mypClass.tl[0].X
A data heirachy like this might work for you (no time to add actual code, sorry!). Then you could implement appropriate getters and setters.
Public class Grid {
List<Row>
}
Public class Row{
List<Point>
}
Public Class Point{
public int X { get; set; }
public int Y { get; set; }
}
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; }
}
}