I know this can be done for methods by using an interface. But interfaces cannot have fields or static properties (which would not help because it would specify one value for all classes that implement the interface). I could also have default values for the properties at the abstract class. But ideally I'd like to force every inheriting class to implement values for these properties. Values which can then still be used in abstract methods on the abstract class level.
The benefits of each property:
- Abstract; The base class requires this property to be implemented but doesn't specify a value.
- Static; only store one value per type of implementation, instead of per object.
public interface IPiece
{
readonly int Points;
readonly char Letter;
}
public abstract class Piece
{
public static readonly int Points;
public static readonly char Letter;
}
public class King : Piece, IPiece
{
public int Points = 0;
public int Letter = 'K';
}
The standard pattern for solving this is:
public interface IPiece
{
int Points { get; }
char Letter { get; }
}
public class King : IPiece
{
public int Points => 0;
public char Letter => 'K';
}
There is no need to use static at all, since 0 and K are literals, and thus (like static) are effectively stored only once per class.
Note also that I have removed your abstract class - it is not useful as is since there is no logic in it. An abstract class without logic is conceptually equivalent to an interface (which you already have) so is unnecessary at this stage.
If you really want to use a static then you could use:
public class King : IPiece
{
private static int points = 0;
private static char letter = 'K';
public int Points => points;
public char Letter => letter;
}
but there is no major benefit to that.
You cannot have a static abstract property. Static members of the class are not subject to polymorphism. If you wish to have a property defined in abstract class which should be shared by all implementations and you don't know it in compile-time, you can create a Singleton type for it, or a wrapper around if its not type defined in your code. Then you can have something like this:
public abstract class Piece // or interface
{
public SingletonIntWrapper Points { get; }
public SingletonCharWrapper Letter { get; }
}
First, interfaces can have properties, but they can't have fields (as indicated in the comments on the question).
public interface IPiece
{
int Points {get;} // readonly properties in interfaces must be defined like this
char Letter {get;}
}
You also need to have your abstract class inherit from the interface in order for it to have access to the properties defined within it. Because it is an abstract class, you must mark the properties as abstract
public abstract class Piece : IPiece
{
public abstract int Points {get;}
public abstract char Letter {get;}
}
From there, you can create an implementation (King) of your abstract class (Piece). Since this is not an abstract implementation, you must provide implementations of the properties at this time.
public class King : Piece
{
public override int Points {get; private set;} = 0;
public override char Letter {get; private set;} = 'K';
}
Take a look here for further examples on property inheritance.
You should use a const or static readonly backingfield. (There are differences). Also the abstract class and the interface are redundant. Either let all your pieces derive from Piece or let them implement IPiece.
public interface IPiece
{
int Points { get; }
char Letter { get; }
}
public abstract class Piece : IPiece
{
public abstract int Points { get; }
public abstract char Letter { get; }
}
public class King : Piece
{
public const int POINTS = 0;
public const char LETTER = 'K';
public override int Points { get { return POINTS; } }
public override char Letter { get { return LETTER; } }
}
Note:
Now still you cannot use the public const or static readonly in a very usefull way. Because you cannot reach the definition of the value without an instance. For example you cannot get the value of the King.LETTER when enumerating all values to determine what Piece to construct based on a character.
Related
I would like to declare a generic field inside PakFileFormat class in order to be replaceable with concrete types in derived classes.
This will be fine:
public class Pak10File : PakFileFormat
{
public Pak10File()
{
this.toc = new PakFileToc<Pak10FileEntry>();
}
}
How to fix this ?
Thanks.
Related classes
public abstract class PakFileEntry { }
public class Pak10FileEntry : PakFileEntry
{
public long size; // 8 bytes
public long csize; // 8 bytes
public long offset; // 8 bytes
public byte fname_len; // 1 byte
public char[] fname; // variable
}
public class PakFileToc<T> where T : PakFileEntry { }
public abstract class PakFileFormat
{
protected PakFileToc<T>; // ----- This does not compile.
}
You would need to make PakFileFormat generic also in order to make that compile.
In order for this to be useful though, you will probably need to make PakFileFormat implement some kind of non-generic interface.
It is hard to give more detail than this without knowing exactly what you need PakFileFormat to actually do, or how it will be used.
public abstract class PakFileFormat<TPakFile> where TPakFile : PakFileEntry
{
protected PakFileToc<TPakFile> toc;
}
The sub-classes would then look something like:
public class Pak10File : PakFileFormat<Pak10FileEntry>
{
public Pak10File()
{
this.toc = new PakFileToc<Pak10FileEntry>();
}
}
public class Foo
{
public const int type = 1;
}
Why can't i do this? Is there a reason behind it or am I trying to access the constant in a wrong way?
new Foo().type;
I know I can do Foo.type but given my scenario, I cant do that. For example if I have two class which inherit from a base class like this:
public class Base
{
...
}
public class Foo : Base
{
public const int type = 0;
}
public class Bar : Base
{
public const int type = 1;
}
public static void printType(Base b)
{
Console.WriteLine(b.type);
}
I would want to get the type property of the class sent through the printType() function but I cant since I can only access the type from the Class, not the object its self.
A work around would be to do
if(b is Foo){
Console.Write(Foo.type);
}elseif....
but this seems stupid and not viable if you have many sub classes of Base
Solution
I ended up using readonly instead of const like this:
public readonly int type = 0;
Yes, you're trying to access it in the wrong way. A constant isn't associated with an instance of a type - it's associated with the type itself. So you want:
int x = Foo.type;
Basically, const members are implicitly static, and C# doesn't let you access static members as if they were instance members, via a value. (Note that in .NET naming conventions, it should be Type rather than type.)
EDIT: Now that you've explained the actual situation, it appears you're trying to use polymorphism, which won't work for constants. So instead, you should have an abstract property in the base class, implemented in subclasses.
public abstract class Base
{
public abstract int Type { get; }
}
public class Foo : Base
{
public override int Type { get { return 0; } }
}
public class Bar : Base
{
public override int Type { get { return 0; } }
}
Alternatively, just have a normal property in the base class which is populated via the base class constructor:
public class Base
{
private readonly int type;
public int Type { get { return type; } }
protected Base(int type)
{
this.type = type;
}
}
public class Foo : Base
{
public Foo() : base(0) {}
}
public class Bar : Base
{
public Bar() : base(1) {}
}
If you just want something to identify the dynamic (most-derived) type of the object passed in, that's built into .NET, via the Object.GetType() method.
public static void printType(Base b)
{
Console.WriteLine(b.GetType().Name);
}
Of course, this isn't quite the same as having attached data under your control. You can, however, use a Dictionary<Type, T> to associate data of arbitrary type with the various subclasses. It would be reasonable to use the subclass type initializer to install new entries into such a dictionary.
public class Base
{
static internal readonly Dictionary<System.Type, int> TypeMap =
new Dictionary<System.Type, int>();
}
public class Foo : Base
{
static Foo { TypeMap.Add(typeof(Foo), 0); }
}
public class Bar : Base
{
static Bar { TypeMap.Add(typeof(Bar), 1); }
}
public static void printType(Base b)
{
Console.WriteLine(Base.TypeMap[b.GetType()]);
}
This WILL be a bit slower than the field-per-object method, however it doesn't add any extra storage per-object.
If I have a very simple class like so:
public class Example
{
public int Number { get; set; }
public Example(int numberArg)
{
this.Number = numberArg;
}
}
And I have a derivative class like so:
public class AnotherExample : Example
{
public int DoubleNumber
{
get
{
return this.Number * 2;
}
}
public AnotherExample(int numberArg) : base(numberArg) {}
}
What difference is there, if any, if I use this.Number to refer to the AnotherExample objects base Number property than if I use base.Number to refer to it?
Thanks!
If Number is not overridden there is no difference, as this.Number will resolve correctly in the chain of inheritance.
This also means that calling this.Member in a base class, if overridden in a derived class will again use the inheritance chain and find the derived implementation.
If it has been overridden, using base will always go to the base class's version of that property, whereas this.Number will first go to your overridden version.
If you plan on calling virtual members inside your constructors, please be aware of the general advice around it:
Virtual member call in a constructor
This answer is leaving out the explanation about member hiding as the OP example is simpler than that.
In this case, there is no difference. In case you override it will take the value from the base class instead of the inherited class:
public class Example {
public virtual int Number { get; set; }
public Example(int numberArg) {
this.Number = numberArg;
}
}
public class AnotherExample : Example {
public override int Number
{
get{return 5;}
set{}
}
public int DoubleNumber {
get {
return this.Number * 2; // returns 10
return base.Number * 2 // returns 2 times whatever the value is
}
}
public AnotherExample(int numberArg) : base(numberArg) {}
}
You can have a variable in derived class that has the same name with in the base class.In this case you need to use this and base keywords to avoid ambiguity.For example:
public class Base
{
public int Number = 0;
}
public class Derived : Base
{
public int Number;
public Derived()
{
this.Number = base.Number + 5;
}
}
I am trying to accomplish the following scenario that the generic TestClassWrapper will be able to access static properties of classes it is made of (they will all derive from TestClass). Something like:
public class TestClass
{
public static int x = 5;
}
public class TestClassWrapper<T> where T : TestClass
{
public int test()
{
return T.x;
}
}
Gives the error:
'T' is a 'type parameter', which is not valid in the given context.
Any suggestions?
You can't, basically, at least not without reflection.
One option is to put a delegate in your constructor so that whoever creates an instance can specify how to get at it:
var wrapper = new TestClassWrapper<TestClass>(() => TestClass.x);
You could do it with reflection if necessary:
public class TestClassWrapper<T> where T : TestClass
{
private static readonly FieldInfo field = typeof(T).GetField("x");
public int test()
{
return (int) field.GetValue(null);
}
}
(Add appropriate binding flags if necessary.)
This isn't great, but at least you only need to look up the field once...
Surely you can just write this:
public int test()
{
return TestClass.x;
}
Even in a nontrivial example, you can't override a static field so will always call it from your known base class.
Why not just return TestClass.x?
Generics do not support anything related to static members, so that won't work. My advice would be: don't make it static. Assuming the field genuinely relates to the specific T, you could also use reflection:
return (int) typeof(T).GetField("x").GetValue(null);
but I don't recommend it.
Another solution is to simply not make it static, and work with the new() constraint on T to instantiate the object. Then you can work with an interface, and the wrapper can get the property out of any class that implements that interface:
public interface XExposer
{
Int32 X { get; }
}
public class TestClass : XExposer
{
public Int32 X { get { return 5;} }
}
public class XExposerWrapper<T> where T : XExposer, new()
{
public Int32 X
{
get { return new T().X; }
}
}
In fact, you can change that to public static Int32 X on the TestClassWrapper and simply get it out as Int32 fetchedX = XExposerWrapper<TestClass>.X;
Though since whatever code calls this will have to give the parameter T those same constraints, the wrapper class is pretty unnecessary at this point, since that calling code itself could also just execute new T().X and not bother with the wrapper.
Still, there are some interesting inheritance models where this kind of structure is useful. For example, an abstract class SuperClass<T> where T : SuperClass<T>, new() can both instantiate and return type T in its static functions, effectively allowing you to make inheritable static functions that adapt to the child classes (which would then need to be defined as class ChildClass : SuperClass<ChildClass>). By defining protected abstract functions / properties on the superclass, you can make functions that apply the same logic on any inherited object, but customized to that subclass according to its implementations of these abstracts. I use this for database classes where the table name and fetch query are implemented by the child class. Since the properties are protected, they are never exposed, either.
For example, on database classes, where the actual fetching logic is put in one central abstract class:
public abstract class DbClass<T> where T : DbClass<T>, new()
{
protected abstract String FetchQuery { get; }
protected abstract void Initialize(DatabaseRecord row);
public static T FetchObject(DatabaseSession dbSession, Int32 key)
{
T obj = new T();
DatabaseRecord record = dbSession.RetrieveRecord(obj.FetchQuery, key);
obj.Initialize(record);
return obj;
}
}
And the implementation:
public class User : DbClass<User>
{
public Int32 Key { get; private set;}
public String FirstName { get; set;}
public String LastName { get; set;}
protected override String FetchQuery
{ get { return "SELECT * FROM USER WHERE KEY = {0}";} }
protected override void Initialize(DatabaseRecord row)
{
this.Key = DbTools.SafeGetInt(row.GetField("KEY"));
this.FirstName = DbTools.SafeGetString(row.GetField("FIRST_NAME"));
this.LastName = DbTools.SafeGetString(row.GetField("LAST_NAME"));
}
}
This can be used as:
User usr = User.FetchObject(dbSession, userKey);
This is a rather simplified example, but as you see, this system allows a static function from the parent class to be called on the child class, to return an object of the child class.
T is a type, not parameter or variable so you cannot pick any value from any members. Here is a sample code.
public class UrlRecordService
{
public virtual void SaveSlug<T>(T entity) where T : ISlugSupport
{
if (entity == null)
throw new ArgumentNullException("entity");
int entityId = entity.Id;
string entityName = typeof(T).Name;
}
}
public interface ISlugSupport
{
int Id { get; set; }
}
cjk and Haris Hasan have the most-correct answers to the question as asked. However in this comment the OP implies that he is after something else not quite possible in C#: a way to define a contract for a static member in a derived class.
There isn't a way to strictly define this, but it is possible to set up a pattern that may be implied by a base class (or interface); e.g.:
public class TestClass
{
private static int x;
public virtual int StaticX => x;
}
or if not intended to be used directly
public abstract class AbstractTestClass
{
public abstract int StaticX {get;}
}
or (my preference in this contrived example)
public interface ITest
{
int StaticX {get;}
}
Elsewhere, this pattern of a StaticXxx member may be (loosely) associated with implementations that should back the member with static fields (as in TestClass above).
What's kind of fun is that this can be (re)exposed as static by the generic wrapper, because generic statics are isolated to each type used.
public class TestClassWrapper<T> where T : ITest, new()
{
private readonly static T testInstance = new T();
public static int test() => testInstance.x;
}
This uses a new() condition, but an associated static, generic factory pattern for creating ITest (or TestClass or AbstractTestClass) instances may also be used.
However this may not be feasible if you can't have long-lived instances of the class.
In this situation you assume that T is a subclass of TestClass. Subclasses of TestClass will not have the static int x.
I've got a base Class ScenBase and a derived class ScenC. I have a class HexC derived form the base class Hex. I also have a class UnitC derived from the base class Unit. I can set an array of Hex to point to an array of HexC, but the compiler won't let me set a List of Unit to point to a list of UnitC:
// The Core Database for the game scenario.
// Theoretically multiple secenarios can be loaded
// into memory at the same time.
[Serializable]
public class ScenC : ScenBase
{
public bool playable { get; set; }
public HexC[,] hexCs { get; private set; }
public List<UnitC> unitCs { get; private set; }
// A database for every user and AI entity.
public List<ScenV> chViews { get; private set; }
public List<string> characters { get; private set; }
public ScenC(int xDimI, int yDimI) : base (xDimI, yDimI)
{
playable = false;
chViews = new List<ScenV>();
characters = new List<string>();
characters.Add("Supreme");
hexCs = new HexC[xDim, yDim];
hexs = hexCs; //this line complies fine
newHex = (int x, int y) => new HexC(this, x, y);
unitCs = new List<UnitC>();
// **This line won't compile**
unitCs = units;
Init();
}
}
Here are the fields properties for the base class ScenBase:
[Serializable]
public abstract class ScenBase
{
public Hex[,] hexs;
public List<Unit> units { get; protected set; }
public DateTime currGameTime { get; set; }
public int xDim { get; set; }
public int yDim { get; set; }
public double scale { get; protected set; }
protected delegate Hex NewHex(int x, int y);
protected NewHex newHex;
//Rest of Class not shown for simplicity
}
Why Can't I set a List<Hex> to a List<HexC> when that follows the "is a" implicit cast rule, but I can set array to array
This is not possible.
Had it been possible, you would have been able to add a different derived type to the list.
For example:
List<Car> cars = new List<Car>
List<Vehicle> vehicles = cars; //Error!
vehicles.Add(new Bicycle()); //That's not a car!
What you're asking for is called covariance; it's only possible for immutable interfaces (such as IEnumerable<T>)
you could use a list of interfaces (1) where the Hex and Unit conform to the nominated interface in some way. otherwise, you will need to cast.
ref: http://msdn.microsoft.com/en-us/library/dd465120.aspx
btw: any interface of IEnumerable is already covariant (see: http://msdn.microsoft.com/en-us/library/9eekhta0.aspx). Syntax: the out in IEnumerable<out T> defines covariance.
(1) A list of interface
using System;
using System.Collections.Generic;
public interface IHex {
string ToString();
}
public class Hex : IHex
{
public override string ToString() { return "Hex"; }
}
public interface IHexC : IHex {}
public class HexC : Hex
{
public override string ToString() { return "HexC"; }
}
public class Test{
public static void Main()
{
IList<IHex> HexList = new List<IHex>();
HexList.Add(new Hex());
HexList.Add(new HexC());
HexList.Add(new HexC());
foreach(var o in HexList){
Console.WriteLine(o.ToString());
}
}
}
Console output:
Hex
HexC
HexC
Not possible like SLaks said, you could use an interface instead. IList<IHex> for example...
you can't cast a
List<UnitC> // UnitC - to a derived from a Unit class
to a
List<Unit> // Unit - the base class
try with a IUnit interface instead
A general point to consider, in addition to SLaks' explanation as to why your code doesn't work is that using a generic defines a new type:
Unit is a type.
UnitC is a type derived from Unit.
List<Unit> is a new type.
List<UnitC> is a new type, but is not derived from List<Unit>.
However,
Hex[] defines multiple instances of the Hex type.
HexC[] defines multiple instances of the HexC type (which is derived from Hex).
Your assignment doesn't work because the compiler can't ensure that the elements of units are actually instances of UnitC, but if you attempted the inverse (units = unitCs), that wouldn't work, either, because List < UnitC > isn't derived from List < Unit >.