Short version:
I have an abstract class A. It has a method that needs to know the value of a static class property that is specific to each subclass. The name and type is the same, just the value can be unique for each subclass.
Can I define this static property in the base class A to be able to access it with methods defined in A, but keeping the property's values of different subclasses unrelated?
Or how would I implement something like that?
Long version:
Let's say I have an abstract base class for data models. It has a public property Id (Int32).
I would like to implement a constructor in the base class that generates a new ID based on the last assigned ID for objects of a subclass.
The reason is that the real IDs are assigned automatically by the database, but each data model object already has to have a unique ID when it gets constructed without being written to the database yet. As the database assigns only positive integers as ID, my plan is to assign newly created data model objects a temporary, unique negative ID. As soon as the object gets written, the ID will get changed to the real one.
As I have quite a few different data model classes all deriving from my abstract base class, I thought it would be good to include that functionality there to not duplicate it. But each subclass has to have their own counter that points to the next free negative ID, as the different classes' IDs are unrelated.
So I need a static property in each subclass storing this class' last assigned temporary ID, but the mechanism to assign it is always the same and could be implemented into the abstract base class' constructor. However, I can't access a property from the base class that has to be implemented by the subclasses, which means I have to define it in the base class. But will this static property then be global for all subclasses, which is not what I want?
How can I implement this temporary ID counter the most elegant way?
Simplified code example:
public abstract class ModelBase
{
public Int32 Id { get; set; }
protected static Int32 LastTempId { get; set; } = 0;
public ModelBase()
{
Id = --LastTempId;
}
}
public class Model1 : ModelBase
{
public Model1 () : base ()
{
// do something model1-specific
}
}
public class Model2 : ModelBase
{
public Model2() : base()
{
// do something model2-specific
}
}
If I implement it like this, I fear that for both subclasses model1 and model2, the inherited static property LastTempId will be the same instance. But I want a separate counter for each subclass while still using it in the base class constructor.
Short answer
The sub-classes cannot have different values for the static property because the static property is a property of the class, not of it's instances, and it's not inherited.
Long answer
You could implement a single counter on the abstract class as a static property and have one constructor of the abstract class using it.
EDIT: To save different counters for each sub-class you could use a static dictionary mapping a Type (sub-class) to a counter.
public abstract class A<T>
{
public static Dictionary<Type, int> TempIDs = new Dictionary<Type, int>();
public int ID { get; set; }
public A()
{
if (!TempIDs.ContainsKey(typeof(T)))
TempIDs.Add(typeof(T), 0);
this.ID = TempIDs[typeof(T)] - 1;
TempIDs[typeof(T)]--;
}
}
public class B : A<B>
{
public string Foo { get; set; }
public B(string foo)
: base()
{
this.Foo = foo;
}
}
public class C : A<C>
{
public string Bar { get; set; }
public C(string bar)
: base()
{
this.Bar = bar;
}
}
B b1 = new B("foo");
B b2 = new B("bar");
C c1 = new C("foo");
C c2 = new C("foo");
b1.ID would be -1, b2.ID would be -2, c1.ID would be -1 and c2.ID would be -2
First of all, my humble opinion is entities shouldn't be responsible of assigning their own unique identifier. Keep a clear separation of concerns.
There should be another player in that game that should assign those temporary unique identifiers (either if they're negative or positive integers).
Usually, that so-called other player is an implementation of repository design pattern which is responsible of translating the domain (your models) into the definitive representation of your data and vice versa.
Usually a repository has a method to add objects. And this should be the point where you set these temporary identifiers:
public void Add(Some some)
{
some.Id = [call method here to set the whole id];
}
And, most repository implementations are per entity.
CustomerRepository
InvoiceRepository
...
...but this doesn't prevent you from defining a base repository class which could implement what can be in common when handling some entity types:
public interface IRepository<TEntity> where TEntity : EntityBase
{
// Other repository methods should be defined here
// but I just define Add for the convenience of this
// Q&A
void Add(TEntity entity);
}
public class Repository<TEntity> : IRepository<TEntity>
where TEntity : EntityBase
{
public virtual void Add(TEntity entity)
{
entity.Id = [call method here to set the whole id];
}
}
...and now any class deriving Repository<TEntity> will be able to generate a temporary identifier for their specialized entities:
public class CustomerRepository : Repository<Customer> { }
public class InvoiceRepository : Repository<Invoice> { }
How you could implement the unique and temporary entity identifier as part of the abstract repository class and being able to do so for each specific entity type?
Use a dictionary to store per-entity last assigned identifier implementing a property to Repository<TEntity>:
public Dictionary<Type, int> EntityIdentifiers { get; } = new Dictionary<Type, int>();
...and a method to decrease next temporary identifier:
private static readonly object _syncLock = new object();
protected virtual void GetNextId()
{
int nextId;
// With thread-safety to avoid unwanted scenarios.
lock(_syncLock)
{
// Try to get last entity type id. Maybe the id doesn't exist
// and out parameter will set default Int32 value (i.e. 0).
bool init = EntityIdentifiers.TryGetValue(typeof(TEntity), out nextId);
// Now decrease once nextId and set it to EntityIdentifiers
nextId--;
if(!init)
EntityIdentifiers[typeof(TEntity)] = nextId;
else
EntityIdentifiers.Add(typeof(TEntity), nextId);
}
return nextId;
}
Finally, your Add method could look as follows:
public virtual void Add(TEntity entity)
{
entity.Id = GetNextId();
}
One way to go is reflection, but it takes run-time and is prone to runtime errors. As others mentioned: you cannot force inheriting classes to redeclare some static field and be able to use this field in ancestor class. So I think minimal code redundancy is necessary: each inheriting class should provide it's own key generator. This generator can be kept in static field of the class of course.
(Note this is not necessarily thread-safe.)
class KeyGenerator
{
private int _value = 0;
public int NextId()
{
return --this._value;
}
}
abstract class ModelBase
{
private KeyGenerator _generator;
public ModelBase(KeyGenerator _generator)
{
this._generator = _generator;
}
public void SaveObject()
{
int id = this._generator.NextId();
Console.WriteLine("Saving " + id.ToString());
}
}
class Car : ModelBase
{
private static KeyGenerator carKeyGenerator = new KeyGenerator();
public Car()
: base(carKeyGenerator)
{
}
}
class Food : ModelBase
{
private static KeyGenerator foodKeyGenerator = new KeyGenerator();
public Food()
: base(foodKeyGenerator)
{
}
}
class Program
{
static void Main(string[] args)
{
Food food1 = new Food();
Food food2 = new Food();
Car car1 = new Car();
food1.SaveObject();
food2.SaveObject();
car1.SaveObject();
}
}
This produces:
Saving -1
Saving -2
Saving -1
Just generate a GUID for each object before it gets added to your database. You could have an isAdded flag that tells you the object should be referred to be GUID, or clear the GUID once the object is added. With a GUID you never have to worry that two objects will clash. Also it obviates the need for separate IDs per subclass. I would not reuse the same property for two states as you propose.
https://msdn.microsoft.com/en-us/library/system.guid(v=vs.110).aspx
Well, static classes aren't inherited, so that's out,m and you can't force subclasses to implement a static method, so that's out too.
Rather than putting that method in the class itself, why not have a base interface that you can implement. Then you can have an instance method that can be abstract:
public interface IDataModelFactory<T> where T:ModelBase
{
int GetLastTempId();
}
public Model1Factory : IDataModelFactory<Model1>
{
public int GetLastTempId()
{
// logic for Model1
}
}
public Model2Factory : IDataModelFactory<Model2>
{
public int GetLastTempId()
{
// logic for Model2
}
}
Or if the logic is common to all classes, have an abstract base class with (or without) the interface:
public DataModelFactory<T> : IDataModelFactory<T>
{
public virtual int GetLastTempId()
{
// common logic
}
// other common logic
}
You could even make the factories singletons so you don't have to create instances all the time, and they can even be sub-classes of the model classes so they're closely linked.
As a side note, if you're uncertain what the inheritance/interface relationship would be, I often find it's quicker start with copy/paste reuse and refactor your code to introduce base classes and interfaces. That way you know what the common code is and can refactor that into common methods. Otherwise you are tempted to try and put everything in the base class and use switches or other constructs to change logic based on the derived type.
Related
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 run into an interesting problem and am looking for some suggestions on how best to handle this...
I have an abstract class that contains a static method that accepts a static string that I would like to define as an abstract property. Problem is that C# doesn't doesn't support the following (see the ConfigurationSectionName and Current properties):
public abstract class ProviderConfiguration : ConfigurationSection
{
private const string _defaultProviderPropertyName = "defaultProvider";
private const string _providersPropertyName = "providers";
protected static string ConfigurationSectionName { get; }
public static Configuration Current
{
get { return Configuration)ConfigurationManager.GetSection(ConfigurationSectionName); }
}
}
I suppose one way to handle this would be to make ConfigurationSectionName NOT abstract and then create a new definition of ConfigurationSectionName in the derived classes, but that feels pretty hackish. Any suggestions would be most welcome.
Gratias!!!
Static members do not have polymorphism, so they can't be abstract. :(
If that's what you need, consider making a Singleton object, and reading the property off that object.
Just use new to override a static method in a derived class. Nothing that makes new a bad thing to do for virtual methods and properties applies since the type name must be supplied:
public class BaseClass
{
public static int Max { get { return 0; } }
}
public class InteriorClass : BaseClass
{
}
public class DerivedClass : InteriorClass
{
public new static int Max { get { return BaseClass.Max + 1; } }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("BaseClass.Max = {0}", BaseClass.Max);
Console.WriteLine("InteriorClass.Max = {0}", InteriorClass.Max);
Console.WriteLine("DerivedClass.Max = {0}", DerivedClass.Max);
Console.ReadKey();
}
}
Ok, this is not exactly to create an static abstract property, but you can achieve the desired effect.
You can get this by using generics:
public abstract class MyAbstractClass<T>
{
public static string MyAbstractString{ get; set; }
public static string GetMyAbstracString()
{
return "Who are you? " + MyAbstractString;
}
}
public class MyDerivedClass : MyAbstractClass<MyDerivedClass>
{
public static new string MyAbstractString
{
get
{
return MyAbstractClass<MyDerivedClass>.MyAbstractString;
}
set
{
MyAbstractClass<MyDerivedClass>.MyAbstractString = value;
}
}
}
public class MyDerivedClassTwo : MyAbstractClass<MyDerivedClassTwo>
{
public static new string MyAbstractString
{
get
{
return MyAbstractClass<MyDerivedClassTwo>.MyAbstractString;
}
set
{
MyAbstractClass<MyDerivedClassTwo>.MyAbstractString = value;
}
}
}
public class Test
{
public void Test()
{
MyDerivedClass.MyAbstractString = "I am MyDerivedClass";
MyDerivedClassTwo.MyAbstractString = "I am MyDerivedClassTwo";
Debug.Print(MyDerivedClass.GetMyAbstracString());
Debug.Print(MyDerivedClassTwo.GetMyAbstracString());
}
}
So, calling the test class you will get:
"Who are you? I am MyDerivedClass"
"Who are you? I am MyDerivedClassTwo"
So, you have an static method in an abstract class but the abstract value is different for each derived class, nice :D
Ok, so, what's going here? The trick is the generic tag, the compiler is generating a different abstract class for each derived type.
As I said it's not an abstract property, but you get all benefits of abstract static properties, which are programming static functions on your abstract class but using different static parameters per type.
Elsewhere on this page, #Gusman proposes the nice solution distilled here:
abstract class AbstractBase { };
abstract class AbstractBase<T> : AbstractBase
{
public static String AbstractStaticProp { get; set; }
};
class Derived1 : AbstractBase<Derived1>
{
public static new String AbstractStaticProp
{
get => AbstractBase<Derived1>.AbstractStaticProp;
set => AbstractBase<Derived1>.AbstractStaticProp = value;
}
};
class Derived2 : AbstractBase<Derived2>
{
public static new String AbstractStaticProp
{
get => AbstractBase<Derived2>.AbstractStaticProp;
set => AbstractBase<Derived2>.AbstractStaticProp = value;
}
};
Moving the static property from a non-generic to generic class means there is no longer necessarily a single global instance. There will be a unique AbstractStaticProp for each distinct type T, so the idea is that specifying the type of the derived class(es) themselves for T guarantees each of them generates a unique static for themselves. There are a few hazards to note with this, however.
If for some reason it is not acceptable for AbstractBaseClass to be generic, then you've only moved the problem elsewhere (albeit more clearly distilled), because you still have to figure out how to statically call from AbstractBase to AbstractBase<T>.
Mainly, there is nothing to enforce or require that any/every given derived class actually does "implement" the (psudo-) "overridden" static property;
Related to this, since there is no compiler (polymorphic) unification going on here, correct signatures (method name, parameter arity, typing, etc.) for the "overridden" methods aren't enforced either.
Although the generic parameter is intended to be "TSelf" of a derived class, in reality T is unconstrained and essentially arbitrary. This opportunizes two new classes of bug: if base class specification Y : AbstractBase<...> mistakenly references a different AbstractBase‑derived class X, the values of the "abstract static property" for X and Y will be incorrectly conflated -- and/or -- any usage call-site AbstractBase<T>.AbstractStaticProp with a mistaken type argument (such as DateTime) will spontaneously--and silently--demand a fresh new "instance" of the static property.
The last bullet point can be somewhat mitigated by adding a constraint on the generic base:
/// v---- constraint added
abstract class AbstractBase<TSelf> where TSelf : AbstractBase<TSelf>
{
public static String AbstractStaticProp { get; set; }
};
This eliminates the possibility of class Derived2 : AbstractBase<DateTime> { /*...*/ }, but not the error class Derived2 : AbstractBase<Derived1> { /*...*/ }. This is due to a recurring conundrum that foils all attempts at constraining a generic type to some exact branch of the type-inheritance hierarchy:
The "TSelf problem"
Generic constraints are always at the mercy of the type arguments that are supplied, which seems to entail that it's impossible to construct a generic constraint that guarantees that some particular TArg within its scope refers to a type that is derived from itself, that is, the immediate type being defined.
The error in this case is an example of this; while the constraint on AbstractBase<TSelf> rules out incompatible disjoint types, it can't rule out the unintended usage Derived2 : AbstractBase<Derived1>. As far as AbstractBase is concerned, the supplied type argument Derived1 satisfies its constraint just fine, regardless of which of its subtypes is deriving itself (im-)properly. I've tried everything, for years, to solve TSelf; if anyone knows a trick I've missed, please let me know!
Anyway, there are still a couple other points to mention. For example, unless you can immediately spot the problem in the following code, you'll have to agree that it's a bit dangerous:
public static new String AbstractStaticProp
{
get => AbstractBase<Derived1>.AbstractStaticProp;
set => AbstractBase<Derived2>.AbstractStaticProp = value;
}
Ideally, you want to get the compiler to do what it's meant to, namely, understand that all AbstractStaticProp property instances are related and thus somehow enforce their unification. Since that's not possible for static methods, the only remaining option is to eliminate the extra versions, effectively reducing the problem to the unification of just one, a vacuous operation, obviously.
It turns out that the original code is being too elaborate; the generic-base class approach wants to collapse on the simpler solution all by itself without having to explicitly request it, such as those new-marked properties seem to be doing with the qualification in AbstractBase<Derived1>.AbstractStaticProp".
You can already refer to each respective independent copy of the static property by qualifying with the derived class name instead (in fact, #Gusman's test harness shows this), so the end result is that the property declarations in the derived class aren't necessary at all. Without further ado, here is the complete simplified version:
abstract class AbstractBase { };
abstract class AbstractBase<TSelf> : AbstractBase
where TSelf : AbstractBase<TSelf>
{
public static String AbstractStaticProp { get; set; }
};
class Derived1 : AbstractBase<Derived1> { };
class Derived2 : AbstractBase<Derived2> { };
This works identically to the code at the top. The test harness gives the same results as before.
static void Test()
{
Derived1.AbstractStaticProp = "I am Derived1";
Derived2.AbstractStaticProp = "I am Derived2";
Debug.Print(Derived1.AbstractStaticProp); // --> I am Derived1
Debug.Print(Derived2.AbstractStaticProp); // --> I am Derived2
}
What you're trying to do is impossible, as others have mentioned.
I'd try something like this
public abstract class ProviderConfiguration : ConfigurationSection
{
public string ConfigurationSectionName { get; set; }
public static ProviderConfiguration Provider { get; set; }
public static Configuration Current
{
get { return (Configuration)ConfigurationManager.GetSection(Provider.ConfigurationSectionName); }
}
}
Then in practice:
public void DoStuff()
{
var provider = new DerivedProviderConfiguration();
ProviderConfiguration.Provider = provider;
}
In my current project I need to be able to have both editable and read-only versions of classes. So that when the classes are displayed in a List or PropertGrid the user is not able to edit objects they should not be allowed to.
To do this I'm following the design pattern shown in the diagram below. I start with a read-only interface (IWidget), and then create an edtiable class which implements this interface (Widget). Next I create a read-only class (ReadOnlyWidget) which simply wraps the mutable class and also implements the read only interface.
I'm following this pattern for a number of different unrelated types. But now I want to add a search function to my program, which can generate results that include any variety of types including both mutable and immutable versions. So now I want to add another set of interfaces (IItem, IMutableItem) that define properties which apply to all types. So IItem defines a set of generic immutable properties, and IMutableItem defines the same properties but editable. In the end a search will return a collection of IItems, which can then later be cast to more specific types if needed.
Yet, I'm not sure if I'm setting up the relationships to IMutable and IItem correctly. Right now I have each of the interfaces (IWidget, IDooHickey) inheriting from IItem, and then the mutable classes (Widget, DooHickey) in addition also implement IMutableItem.
Alternatively, I was also thinking I could then set IMutableItem to inherit from IItem, which would hide its read-only properties with new properties that have both get and set accessors. Then the mutable classes would implement IMutableItem, and the read-only classes would implement IItem.
I'd appreciate any suggestions or criticisms regarding any of this.
Class Diagram
Code
public interface IItem
{
string ItemName { get; }
}
public interface IMutableItem
{
string ItemName { get; set; }
}
public interface IWidget:IItem
{
void Wiggle();
}
public abstract class Widget : IWidget, IMutableItem
{
public string ItemName
{
get;
set;
}
public void Wiggle()
{
//wiggle a little
}
}
public class ReadOnlyWidget : IWidget
{
private Widget _widget;
public ReadOnlyWidget(Widget widget)
{
this._widget = widget;
}
public void Wiggle()
{
_widget.Wiggle();
}
public string ItemName
{
get {return _widget.ItemName; }
}
}
public interface IDoohickey:IItem
{
void DoSomthing();
}
public abstract class Doohickey : IDoohickey, IMutableItem
{
public void DoSomthing()
{
//work it, work it
}
public string ItemName
{
get;
set;
}
}
public class ReadOnlyDoohickey : IDoohickey
{
private Doohickey _doohicky;
public ReadOnlyDoohickey(Doohickey doohicky)
{
this._doohicky = doohicky;
}
public string ItemName
{
get { return _doohicky.ItemName; }
}
public void DoSomthing()
{
this._doohicky.DoSomthing();
}
}
Is it OK to create another object when you need a readonly copy? If so then you can use the technique in the included code. If not, I think a wrapper is probably your best bet when it comes to this.
internal class Test
{
private int _id;
public virtual int ID
{
get
{
return _id;
}
set
{
if (ReadOnly)
{
throw new InvalidOperationException("Cannot set properties on a readonly instance.");
}
}
}
private string _name;
public virtual string Name
{
get
{
return _name;
}
set
{
if (ReadOnly)
{
throw new InvalidOperationException("Cannot set properties on a readonly instance.");
}
}
}
public bool ReadOnly { get; private set; }
public Test(int id = -1, string name = null)
: this(id, name, false)
{ }
private Test(int id, string name, bool readOnly)
{
ID = id;
Name = name;
ReadOnly = readOnly;
}
public Test AsReadOnly()
{
return new Test(ID, Name, true);
}
}
I would suggest that for each main class or interface, there be three defined classes: a "readable" class, a "changeable" class, and an "immutable" class. Only the "changeable" or "immutable" classes should exist as concrete types; they should both derive from an abstract "readable" class. Code which wants to store an object secure in the knowledge that it never changes should store the "immutable" class; code that wants to edit an object should use the "changeable" class. Code which isn't going to write to something but doesn't care if it holds the same value forever can accept objects of the "readable" base type.
The readable version should include public abstract methods AsChangeable(), AsImmutable(), public virtual method AsNewChangeable(), and protected virtual method AsNewImmutable(). The "changeable" classes should define AsChangeable() to return this, and AsImmutable to return AsNewImmutable(). The "immutable" classes should define AsChangeable() to return AsNewChangeable() and AsImmutable() to return this.
The biggest difficulty with all this is that inheritance doesn't work terribly well if one tries to use class types rather than interfaces. For example, if one would like to have an EnhancedCustomer class which inherits from BasicCustomer, then ImmutableEnhancedCustomer should inherit from both ImmutableBasicCustomer and ReadableEnhancedCustomer, but .net doesn't allow such dual inheritance. One could use an interface IImmutableEnhancedCustomer rather than a class, but some people would consider an 'immutable interace' to be a bit of a smell since there's no way a module that defines an interface in such a way that outsiders can use it without also allowing outsiders to define their own implementations.
Abandon hope all ye who enter here!!!
I suspect that in the long run your code is going to be very confusing. Your class diagram suggests that all properties are editable (or not) in a given object. Or are your (I'm)mutable interfaces introducing new properties that are all immutable or not, separate from the "core"/inheriting class?
Either way I think you're going to end up with playing games with property name variations and/or hiding inherited properties
Marker Interfaces Perhaps?
Consider making all properties in your classes mutable. Then implement IMutable (I don't like the name IItem) and IImutable as a marker interfaces. That is, there is literally nothing defined in the interface body. But it allows client code to handle the objects as a IImutable reference, for example.
This implies that either (a) your client code plays nice and respects it's mutability, or (b) all your objects are wrapped by a "controller" class that enforces the given object's mutability.
Could be too late :-), but the cause "The keyword 'new' is required on property because it hides property ..." is a bug in Resharper, no problem with the compiler. See the example below:
public interface IEntityReadOnly
{
int Prop { get; }
}
public interface IEntity : IEntityReadOnly
{
int Prop { set; }
}
public class Entity : IEntity
{
public int Prop { get; set; }
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var entity = new Entity();
(entity as IEntity).Prop = 2;
Assert.AreEqual(2, (entity as IEntityReadOnly).Prop);
}
}
Same for the case without interfaces. The only limitation, you can't use auto-properties
public class User
{
public User(string userName)
{
this.userName = userName;
}
protected string userName;
public string UserName { get { return userName; } }
}
public class UserUpdatable : User
{
public UserUpdatable()
: base(null)
{
}
public string UserName { set { userName = value; } }
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var user = new UserUpdatable {UserName = "George"};
Assert.AreEqual("George", (user as User).UserName);
}
}
I want to force subclasses to define a constant value.
Like
const string SomeConstantEverySubclassMustDefine = "abc";
I need that because I need to have it tied to the Type, rather than to the instance and you can't override static Methods/Properties iirc.
I'd really like to have a compile-time check for those constants.
Let me explain in more detail:
Some classes in our Domain-Model are special, you can take certain actions for them, depending on the type. Thus the logic is tied to the type. The action to be taken requires a string tied to the type. I sure could create an instance everytime as a workaround and declare an abstract property, but that's not what I want. I want to enforce the declaration of the string at compile-time, just to be sure.
No, you can't. I would suggest you make your base class abstract, with an abstract property which you can fetch when you want. Each child class can then implement the property just by returning a constant if it wants. The downside is that you can't use this within static methods in the base class - but those aren't associated with the child classes anyway.
(It also allows child classes to customise the property per instance as well, if necessary... but that's rarely an actual problem.)
If this doesn't do enough for you, you might want to consider a parallel type hierarchy. Basically polymorphism simply doesn't happen in a type-specific way in .NET; only in an instance-specific way.
If you still want to do this and fetch it with reflection, I suggest you just write unit tests to ensure that the relevant constants are defined. When you get beyond what the type system can describe, that's often the best you can do.
Make an abstract property with only a get. That's what I think you could do to enforce a class has a value. Then you can just return a constant in the property.
Example:
Base class:
public abstract string MyConst { get; }
Derived class:
public override string MyConst {
get { return "constant"; }
}
Here is how I made mine work. I used Attribute as others have suggested.
public class ObjectAttribute : Attribute
{
public int ObjectSize { get; set; }
public ObjectAttribute(int objectSize)
{
this.ObjectSize = objectSize;
}
}
public abstract class BaseObject
{
public static int GetObjectSize<T>() where T : IPacket
{
ObjectAttribute[] attributes = (ObjectAttribute[])typeof(T).GetCustomAttributes(typeof(ObjectAttribute), false);
return attributes.Length > 0 ? attributes[0].ObjectSize : 0;
}
}
[ObjectAttribute(15)]
public class AObject : BaseObject
{
public string Code { get; set; }
public int Height { get; set; }
}
[ObjectAttribute(25)]
public class BObject : BaseObject
{
public string Code { get; set; }
public int Weight { get; set; }
}
If you would like instance access to the attribute just add it to the base abstract class.
public abstract class BaseObject
{
public static int GetObjectSize<T>() where T : IPacket
{
ObjectAttribute[] attributes = (ObjectAttribute[])typeof(T).GetCustomAttributes(typeof(ObjectAttribute), false);
return attributes.Length > 0 ? attributes[0].ObjectSize : 0;
}
public int ObjectSize
{
get
{
ObjectAttribute[] attributes = (ObjectAttribute[])GetType().GetCustomAttributes(typeof(ObjectAttribute), false);
return attributes.Length > 0 ? attributes[0].ObjectSize : 0;
}
}
}
Usage of the constants
int constantValueA = AObject.GetObjectSize<AObject>();
int constantValueB = BObject.GetObjectSize<BObject>();
AObject aInstance = new AObject();
int instanceValueA = aInstance.ObjectSize;
New idea
Here's a sort of weird idea: instead of using inheritance directly, you create a separate class to provide a constant value for every type deriving from some type T. The constructor for this type uses reflection to verify that every derived type has indeed been supplied a value.
public abstract class Constant<T, TConstant>
{
private Dictionary<Type, TConstant> _constants;
protected Constant()
{
_constants = new Dictionary<Type, TConstant>();
// Here any class deriving from Constant<T, TConstant>
// should put a value in the dictionary for every type
// deriving from T, using the DefineConstant method below.
DefineConstants();
EnsureConstantsDefinedForAllTypes();
}
protected abstract void DefineConstants();
protected void DefineConstant<U>(TConstant constant) where U : T
{
_constants[typeof(U)] = constant;
}
private void EnsureConstantsDefinedForAllTypes()
{
Type baseType = typeof(T);
// Here we discover all types deriving from T
// and verify that each has a key present in the
// dictionary.
var appDomain = AppDomain.CurrentDomain;
var assemblies = appDomain.GetAssemblies();
var types = assemblies
.SelectMany(a => a.GetTypes())
.Where(t => baseType.IsAssignableFrom(t));
foreach (Type t in types)
{
if (!_constants.ContainsKey(t))
{
throw new Exception(
string.Format("No constant defined for type '{0}'.", t)
);
}
}
}
public TConstant GetValue<U>() where U : T
{
return _constants[typeof(U)];
}
}
Basic example:
public class BaseType
{
public static Constant<BaseType, string> Description { get; private set; }
static BaseType()
{
Description = new BaseTypeDescription();
}
}
public class DerivedType : BaseType
{ }
internal sealed class BaseTypeDescription : Constant<BaseType, string>
{
public BaseTypeDescription() : base()
{ }
protected override DefineConstants()
{
DefineConstant<BaseType>("A base type");
DefineConstant<DerivedType>("A derived type");
}
}
Now I have code that allows me to do this:
var description = BaseType.Description;
// returns "A base type"
string baseTypeDescription = description.GetValue<BaseType>();
// returns "A derived type"
string derivedTypeDescription = description.GetValue<DerivedType>();
Original answer
You may not like it, but the closest way to accomplish this is by declaring an abstract read-only (no set) property.
If you've got an instance of your subclass, then this can work just as well as a constant, even though it is technically instance-level (it will just be the same for all instances of the given class).
Consider, for instance, IList.IsReadOnly. In most cases this is actually a property that tells you about the underlying class implementation, as opposed to any state specific to a particular instance. (It may be an interface member as opposed to an abstract class member, but it's the same idea.)
If you are trying to access it statically, well... then you're out of luck. But in this case I fail to see how you'd obtain the value without using reflection anyway. Maybe that's your intention; I don't know.
You could have a static method in the base class called, for instance "Register", that is passed a Type and a constant value, with the intention being that it is called by the class constructors of the subtypes. Then, add a check in all of your base class constructors that the object being constructed is of a registered type.
abstract class Base
{
private static Dictionary<Type, string> _registry = new Dictionary<Type, string>();
protected static void Register(Type t, string constVal)
{
_registry.Add(t, constVal);
}
protected Base()
{
if(!_registry.ContainsKey(this.GetType()))
throw new NotSupportedException("Type must have a registered constant");
}
public string TypeConstant
{
get
{
return _registry[this.GetType()];
}
}
}
class GoodSubtype : Base
{
static GoodSubtype()
{
Base.Register(typeof(GoodSubtype), "Good");
}
public GoodSubtype()
: base()
{
}
}
class Badsubtype : Base
{
public Badsubtype()
: base()
{
}
}
And then elsewhere, you can construct GoodSubtype instances, but trying to construct a Badsubtype gets an exception. I think a runtime error at construction is the soonest you can get an error with this type of scheme.
(You'd want to use ConcurrentDictionary for your registry if threading is involved)
There's one other method that hasn't been covered and it uses the new modifier to hide consts values in the base class. In a way, it's similar to Nap's solution, but doesn't allow per-instance access and therefore doesn't allow for polymorphic access within the base class. This solution is only useful if you want to have constant value defined but wish to have the option of changing it to different values in different subclasses.
static void Main(string[] args)
{
Console.WriteLine("BaseClass.MyConst = {0}, ClassA.MyConst = {1}, ClassB.MyConst = {2}", BaseClass.MyConst, ClassA.MyConst, ClassB.MyConst);
Console.ReadKey();
}
class BaseClass
{
public const int MyConst = 1;
}
class ClassA : BaseClass
{
public new const int MyConst = 2;
}
class ClassB : BaseClass
{
}
(C#, VS2008) In a program I'm working on, I've got lots of objects that all have an ID and implement IComparable so that List<>-s of the various objects are easily searchable by ID. Since I hate copy/pasting code, I thought I'd abstract that bit of functionality down to a base class, like so:
using System;
namespace MyProg.Logic
{
abstract class IDObject : IComparable<IDObject>
{
private int miID;
public int ID
{
get { return miID; }
set { miID = value; }
}
public IDObject(int ID)
{
miID = ID;
}
#region IComparable<IDObject> Members
int IComparable<IDObject>.CompareTo(IDObject other)
{
return miID.CompareTo(other.miID);
}
#endregion
}
}
The drawback I see to that is that two separate classes that each inherit it would be directly comparable using .CompareTo() and I was hoping to enforce that each class that inherits from IDObject is only Comparable to others of the exact same class. So I was hoping to figure out how to do that and came up with this
using System;
namespace MyProg.Logic
{
abstract class IDObject : IComparable<T> where T : IDObject
{
private int miID;
public int ID
{
get { return miID; }
set { miID = value; }
}
public IDObject(int ID)
{
miID = ID;
}
#region IComparable<T> Members
int IComparable<T>.CompareTo(T other)
{
return miID.CompareTo(other.miID);
}
#endregion
}
}
But that gives a compile error of "Constraints are not allowed on non-generic declarations"
Looking at it, I'm sure there's a way to do something like that so that each class is only comparable to other instances of that same class, but I can't tease out the syntax.
You can use the Curiously Recurring Template Pattern to solve this problem.
abstract class Base<T> : IComparable<T> where T : Base<T> {
public int Rank { get; set; } // Order instances of derived type T by Rank
public int CompareTo(T other) { return Rank.CompareTo(other.Rank); }
}
class Foo : Base<Foo> {}
class Bar : Base<Bar> {}
static class Program {
static void Main() {
var foo1 = new Foo { Rank = 1 };
var foo2 = new Foo { Rank = 2 };
var bar1 = new Bar { Rank = 1 };
var bar2 = new Bar { Rank = 2 };
Console.WriteLine(foo1.CompareTo(foo2));
Console.WriteLine(bar2.CompareTo(bar1));
//error CS1503: Argument '1': cannot convert from 'Bar' to 'Foo'
//Console.WriteLine(foo1.CompareTo(bar1));
}
}
I think you've got bigger problems than just making sure that the derived class types are the same. You are also saddling the derived class with the responsibility to generate a unique ID. That requires the derived class to be aware what other IDs were assigned previously. Realistically, that requires a class factory. You'll need to enforce that by making the constructor of your abstract class protected.
Not very practical. If the ID is just an opaque number that establishes object identity then consider assigning the ID yourself. Use a static member to keep track of the last assigned one. Now it becomes simple, and you don't have to worry about derived class types anymore.