Request for Comments: fast hashed base class for dictonary keys - c#

In one of my aplications I have to use many dictonarys with custom objects as keys. To improve the performance of the lookups I implemetet an base class that overrites GetHashCode.
It seams to work but somehow I still have a bad fealing about it so I decided to post my code and I would be gratefull for any tips or coments.
(omg I forgot the code :D )
abstract class FastHashed
{
private static Dictionary<Type,ulong> _instanceCounters = new Dictionary<Type,ulong>();
private int hash;
protected FastHashed()
{
Type instanceType = this.GetType();
if(! _instanceCounters.ContainsKey(instanceType)) _instanceCounters.Add(instanceType,0);
this.hash = ((instanceType.ToString())+(_instanceCounters[instanceType]++.ToString())).GetHashCode();
}
public override int GetHashCode()
{
return hash;
}
}
Edit: Do not mess with the hashing if you do not have to. This "sollution" is slower and less reliable then the default GetHashCode().
Edit:
I did some performance testing with the Equatec profiler and a simple console aplication.
class Program
{
static readonly int cycles = 50000;
static Dictionary objectsDict = new Dictionary();
static Dictionary foosDict = new Dictionary();
static void Main(string[] args)
{
foo[] foos = new foo[cycles];
object[] objects = new object[cycles];
for (int i = 0; i < cycles; i++)
{
foos[i] = new foo();
objects[i] = new object();
foosDict.Add(foos[i], i);
objectsDict.Add(objects[i], i);
}
ObjectHash(objects);
FooHash(foos);
}
static void ObjectHash(Object[] objects)
{
int value;
for (int i = 0; i < cycles; i++)
{
value = objectsDict[objects[i]];
}
}
static void FooHash(foo[] foos)
{
int value;
for (int i = 0; i < cycles; i++)
{
value = foosDict[foos[i]];
}
}
class foo
{
private readonly int _hash;
public foo()
{
_hash = this.GetHashCode();
}
public override int GetHashCode()
{
return _hash;
}
}
}
The results:
- FooHash 26 774 ms
- ObjectHash 7 ms
Obviously the defualt GetHashCode is the best choice.

This is not thread-safe.
If you only care about reference equality, why do you have different counters for different types?
If all you want is to prevent Hashes from being computed multiple times, why not something like this (or a variant with generics if the dictionary will only hold objects of a certain type):
public class ObjectWithCachedHashCode : IEquatable<ObjectWithCachedHashCode>
{
private int _cachedHashCode;
public object Object { get; private set; }
public ObjectWithCachedHashCode(object obj)
{
Object = obj;
_cachedHashCode = obj.GetHashCode();
}
public override int GetHashCode()
{
return _cachedHashCode;
}
public bool Equals(ObjectWithCachedHashCode other)
{
return other!=null && Object.Equals(other.Object);
}
public override bool Equals(object other)
{
return Equals(other as ObjectWithCachedHashCode);
}
}
Edit: Made class compatible with Dictionary

You can mark the hash variable readonly.
But to be honest, in C# where you have single inheritance it is not always wise to "waste" the inheritance to implement such specific behavior. Suppose you suddenly wants to inherit from a base class that "does" something. Save class inheritance to modelling purposes, not implementing details.

As far as I can see, this is just functionally equivalent to the object.GetHashCode() default implemntation, apart from being slower and non thread-safe. What is it that makes "Fast Hash" fast?

Related

Custom dictionary class in c#

I am trying to create a custom dictionary with some methods. I created a struct containing the information for lanes in my game. One information tells me if there is an enemy in the lane(Occupied) and the other if we completed that lane so no more enemies will come there(Completed).
I am able to get the initial information out, but cannot update them with my methods. I construct it by adding all 7 lanes, where none of them are either occupied or completed. Then throughout my game, I would like to mark them either as completed or occupied or free, but even after a lot of time searching around, I couldn't figure out the proper way to call for an update of these items inside my laneInfo property.
public struct laneInfo
{
public bool Occupied;
public bool Completed;
}
public class laneInfoClass : Dictionary<int, laneInfo>
{
public laneInfo laneinfo;
public laneInfoClass()
{
for(int i = 0; i <= 6; i++)
{
this.Add(i, false, false);
}
}
public void Add(int key, bool occupied, bool completed)
{
laneinfo.Occupied = occupied;
laneinfo.Completed = completed;
this.Add(key, laneinfo);
}
public void Complete()
{
laneinfo.Completed = true;
}
public void Occupy()
{
laneinfo.Occupied = true;
}
public void Free()
{
laneinfo.Occupied = false;
}
}
Thanks!
Its fairly rare that your class would inherit from a dictionary/list/collection (why?), more often than not what you are actually modelling is a class which has an instance member which is that same dictionary/list/collection.
In addition, you need some way to notify your class which particular lane you're trying to update, you use an integer key so work with that:
public struct LaneInfo
{
public bool Occupied {get;set;}
public bool Completed {get;set;}
}
public class LaneInfoContainer
{
private Dictionary<int, LaneInfo> laneInfoDict = new Dictionary<int, LaneInfo>();
public LaneInfoContainer()
{
for(int i = 0; i <= 6; i++)
{
this.Add(i, false, false);
}
}
public void Add(int key, bool occupied, bool completed)
{
var laneInfo = new LaneInfo();
laneinfo.Occupied = occupied;
laneinfo.Completed = completed;
this.laneInfoDict.Add(key, laneinfo);
}
public void Complete(int key)
{
laneInfoDict[key].Completed = true;
}
public void Occupy(int key)
{
laneInfoDict[key].Occupied = true;
}
public void Free(int key)
{
laneInfoDict[key].Occupied = false;
}
}
I suspect you might also need some way to read the info about your lanes too, add methods such as
public bool IsComplete(int key)
{
return laneInfoDict[key].Complete;
}
The answer to your question is that you should not use a Dictionary. Iterating a List<T>.Contains is faster than Dictionary<TKey, TValye> lookup for 7 items, especially if you are accessing them by index integer 0-6.
Part from that, Dictionary<TKey, TValue> is already generic and so there is no need to inherit from it. Sometimes you would wrap it, for various reasons (one might be locking). But if it is just for a few methods you can simply add extension methods to the Dictionary<int, LaneInfo>.
public static class LaneExtensionMethods
{
public static bool IsComplete(this Dictionary<int, LaneInfo> dictionary, int key)
{
return dictionary[key].Complete;
}
}
// Use
var d = new Dictionary<int, LaneInfo>();
var isComplete = d.IsComplete(1);
I often replace the int with a type to avoid bugs and confusion in code. This would in your case also allow for specialized extension methods. Casting has zero CPU cost (its just cosmetics in code).
public enum LaneId : Int32 { }
public static class LaneExtensionMethods
{
public static bool IsComplete(this Dictionary<LaneId, LaneInfo> dictionary, LaneId key)
{
return dictionary[key].Complete;
}
}
// Use
var d = new Dictionary<LaneId, LaneInfo>();
var laneId = (LaneId)1; // We cast from integer to LaneId, but use LaneId type everywhere in our app
var isComplete = d.IsComplete(laneId);

C# enum inheritance [duplicate]

I have an enum in a low level namespace. I'd like to provide a class or enum in a mid level namespace that "inherits" the low level enum.
namespace low
{
public enum base
{
x, y, z
}
}
namespace mid
{
public enum consume : low.base
{
}
}
I'm hoping that this is possible, or perhaps some kind of class that can take the place of the enum consume which will provide a layer of abstraction for the enum, but still let an instance of that class access the enum.
Thoughts?
EDIT:
One of the reasons I haven't just switched this to consts in classes is that the low level enum is needed by a service that I must consume. I have been given the WSDLs and the XSDs, which define the structure as an enum. The service cannot be changed.
This is not possible. Enums cannot inherit from other enums. In fact all enums must actually inherit from System.Enum. C# allows syntax to change the underlying representation of the enum values which looks like inheritance, but in actuality they still inherit from System.enum.
See section 8.5.2 of the CLI spec for the full details. Relevant information from the spec
All enums must derive from System.Enum
Because of the above, all enums are value types and hence sealed
You can achieve what you want with classes:
public class Base
{
public const int A = 1;
public const int B = 2;
public const int C = 3;
}
public class Consume : Base
{
public const int D = 4;
public const int E = 5;
}
Now you can use these classes similar as when they were enums:
int i = Consume.B;
Update (after your update of the question):
If you assign the same int values to the constants as defined in the existing enum, then you can cast between the enum and the constants, e.g:
public enum SomeEnum // this is the existing enum (from WSDL)
{
A = 1,
B = 2,
...
}
public class Base
{
public const int A = (int)SomeEnum.A;
//...
}
public class Consume : Base
{
public const int D = 4;
public const int E = 5;
}
// where you have to use the enum, use a cast:
SomeEnum e = (SomeEnum)Consume.B;
The short answer is no. You can play a bit, if you want:
You can always do something like this:
private enum Base
{
A,
B,
C
}
private enum Consume
{
A = Base.A,
B = Base.B,
C = Base.C,
D,
E
}
But, it doesn't work all that great because Base.A != Consume.A
You can always do something like this, though:
public static class Extensions
{
public static T As<T>(this Consume c) where T : struct
{
return (T)System.Enum.Parse(typeof(T), c.ToString(), false);
}
}
In order to cross between Base and Consume...
You could also cast the values of the enums as ints, and compare them as ints instead of enum, but that kind of sucks too.
The extension method return should type cast it type T.
The solutions above using classes with int constants lack type-safety. I.e. you could invent new values actually not defined in the class.
Furthermore it is not possible for example to write a method taking one of these classes as input.
You would need to write
public void DoSomethingMeaningFull(int consumeValue) ...
However, there is a class based solution of the old days of Java, when there were no enums available. This provides an almost enum-like behaviour. The only caveat is that these constants cannot be used within a switch-statement.
public class MyBaseEnum
{
public static readonly MyBaseEnum A = new MyBaseEnum( 1 );
public static readonly MyBaseEnum B = new MyBaseEnum( 2 );
public static readonly MyBaseEnum C = new MyBaseEnum( 3 );
public int InternalValue { get; protected set; }
protected MyBaseEnum( int internalValue )
{
this.InternalValue = internalValue;
}
}
public class MyEnum : MyBaseEnum
{
public static readonly MyEnum D = new MyEnum( 4 );
public static readonly MyEnum E = new MyEnum( 5 );
protected MyEnum( int internalValue ) : base( internalValue )
{
// Nothing
}
}
[TestMethod]
public void EnumTest()
{
this.DoSomethingMeaningful( MyEnum.A );
}
private void DoSomethingMeaningful( MyBaseEnum enumValue )
{
// ...
if( enumValue == MyEnum.A ) { /* ... */ }
else if (enumValue == MyEnum.B) { /* ... */ }
// ...
}
Ignoring the fact that base is a reserved word you cannot do inheritance of enum.
The best thing you could do is something like that:
public enum Baseenum
{
x, y, z
}
public enum Consume
{
x = Baseenum.x,
y = Baseenum.y,
z = Baseenum.z
}
public void Test()
{
Baseenum a = Baseenum.x;
Consume newA = (Consume) a;
if ((Int32) a == (Int32) newA)
{
MessageBox.Show(newA.ToString());
}
}
Since they're all the same base type (ie: int) you could assign the value from an instance of one type to the other which a cast. Not ideal but it work.
This is what I did. What I've done differently is use the same name and the new keyword on the "consuming" enum. Since the name of the enum is the same, you can just mindlessly use it and it will be right. Plus you get intellisense. You just have to manually take care when setting it up that the values are copied over from the base and keep them sync'ed. You can help that along with code comments. This is another reason why in the database when storing enum values I always store the string, not the value. Because if you are using automatically assigned increasing integer values those can change over time.
// Base Class for balls
public class Ball
{
// keep synced with subclasses!
public enum Sizes
{
Small,
Medium,
Large
}
}
public class VolleyBall : Ball
{
// keep synced with base class!
public new enum Sizes
{
Small = Ball.Sizes.Small,
Medium = Ball.Sizes.Medium,
Large = Ball.Sizes.Large,
SmallMedium,
MediumLarge,
Ginormous
}
}
I know this answer is kind of late but this is what I ended up doing:
public class BaseAnimal : IEquatable<BaseAnimal>
{
public string Name { private set; get; }
public int Value { private set; get; }
public BaseAnimal(int value, String name)
{
this.Name = name;
this.Value = value;
}
public override String ToString()
{
return Name;
}
public bool Equals(BaseAnimal other)
{
return other.Name == this.Name && other.Value == this.Value;
}
}
public class AnimalType : BaseAnimal
{
public static readonly BaseAnimal Invertebrate = new BaseAnimal(1, "Invertebrate");
public static readonly BaseAnimal Amphibians = new BaseAnimal(2, "Amphibians");
// etc
}
public class DogType : AnimalType
{
public static readonly BaseAnimal Golden_Retriever = new BaseAnimal(3, "Golden_Retriever");
public static readonly BaseAnimal Great_Dane = new BaseAnimal(4, "Great_Dane");
// etc
}
Then I am able to do things like:
public void SomeMethod()
{
var a = AnimalType.Amphibians;
var b = AnimalType.Amphibians;
if (a == b)
{
// should be equal
}
// call method as
Foo(a);
// using ifs
if (a == AnimalType.Amphibians)
{
}
else if (a == AnimalType.Invertebrate)
{
}
else if (a == DogType.Golden_Retriever)
{
}
// etc
}
public void Foo(BaseAnimal typeOfAnimal)
{
}
Alternative solution
In my company, we avoid "jumping over projects" to get to non-common lower level projects. For instance, our presentation/API layer can only reference our domain layer, and the domain layer can only reference the data layer.
However, this is a problem when there are enums that need to be referenced by both the presentation and the domain layers.
Here is the solution that we have implemented (so far). It is a pretty good solution and works well for us. The other answers were hitting all around this.
The basic premise is that enums cannot be inherited - but classes can. So...
// In the lower level project (or DLL)...
public abstract class BaseEnums
{
public enum ImportanceType
{
None = 0,
Success = 1,
Warning = 2,
Information = 3,
Exclamation = 4
}
[Flags]
public enum StatusType : Int32
{
None = 0,
Pending = 1,
Approved = 2,
Canceled = 4,
Accepted = (8 | Approved),
Rejected = 16,
Shipped = (32 | Accepted),
Reconciled = (64 | Shipped)
}
public enum Conveyance
{
None = 0,
Feet = 1,
Automobile = 2,
Bicycle = 3,
Motorcycle = 4,
TukTuk = 5,
Horse = 6,
Yak = 7,
Segue = 8
}
Then, to "inherit" the enums in another higher level project...
// Class in another project
public sealed class SubEnums: BaseEnums
{
private SubEnums()
{}
}
This has three real advantages...
The enum definitions are automatically the same in both projects - by
definition.
Any changes to the enum definitions are automatically
echoed in the second without having to make any modifications to the
second class.
The enums are based on the same code - so the values can easily be compared (with some caveats).
To reference the enums in the first project, you can use the prefix of the class: BaseEnums.StatusType.Pending or add a "using static BaseEnums;" statement to your usings.
In the second project when dealing with the inherited class however, I could not get the "using static ..." approach to work, so all references to the "inherited enums" would be prefixed with the class, e.g. SubEnums.StatusType.Pending. If anyone comes up with a way to allow the "using static" approach to be used in the second project, let me know.
I am sure that this can be tweaked to make it even better - but this actually works and I have used this approach in working projects.
I also wanted to overload Enums and created a mix of the answer of 'Seven' on this page and the answer of 'Merlyn Morgan-Graham' on a duplicate post of this, plus a couple of improvements.
Main advantages of my solution over the others:
automatic increment of the underlying int value
automatic naming
This is an out-of-the-box solution and may be directly inserted into your project. It is designed to my needs, so if you don't like some parts of it, just replace them with your own code.
First, there is the base class CEnum that all custom enums should inherit from. It has the basic functionality, similar to the .net Enum type:
public class CEnum
{
protected static readonly int msc_iUpdateNames = int.MinValue;
protected static int ms_iAutoValue = -1;
protected static List<int> ms_listiValue = new List<int>();
public int Value
{
get;
protected set;
}
public string Name
{
get;
protected set;
}
protected CEnum ()
{
CommonConstructor (-1);
}
protected CEnum (int i_iValue)
{
CommonConstructor (i_iValue);
}
public static string[] GetNames (IList<CEnum> i_listoValue)
{
if (i_listoValue == null)
return null;
string[] asName = new string[i_listoValue.Count];
for (int ixCnt = 0; ixCnt < asName.Length; ixCnt++)
asName[ixCnt] = i_listoValue[ixCnt]?.Name;
return asName;
}
public static CEnum[] GetValues ()
{
return new CEnum[0];
}
protected virtual void CommonConstructor (int i_iValue)
{
if (i_iValue == msc_iUpdateNames)
{
UpdateNames (this.GetType ());
return;
}
else if (i_iValue > ms_iAutoValue)
ms_iAutoValue = i_iValue;
else
i_iValue = ++ms_iAutoValue;
if (ms_listiValue.Contains (i_iValue))
throw new ArgumentException ("duplicate value " + i_iValue.ToString ());
Value = i_iValue;
ms_listiValue.Add (i_iValue);
}
private static void UpdateNames (Type i_oType)
{
if (i_oType == null)
return;
FieldInfo[] aoFieldInfo = i_oType.GetFields (BindingFlags.Public | BindingFlags.Static);
foreach (FieldInfo oFieldInfo in aoFieldInfo)
{
CEnum oEnumResult = oFieldInfo.GetValue (null) as CEnum;
if (oEnumResult == null)
continue;
oEnumResult.Name = oFieldInfo.Name;
}
}
}
Secondly, here are 2 derived Enum classes. All derived classes need some basic methods in order to work as expected. It's always the same boilerplate code; I haven't found a way yet to outsource it to the base class. The code of the first level of inheritance differs slightly from all subsequent levels.
public class CEnumResult : CEnum
{
private static List<CEnumResult> ms_listoValue = new List<CEnumResult>();
public static readonly CEnumResult Nothing = new CEnumResult ( 0);
public static readonly CEnumResult SUCCESS = new CEnumResult ( 1);
public static readonly CEnumResult UserAbort = new CEnumResult ( 11);
public static readonly CEnumResult InProgress = new CEnumResult (101);
public static readonly CEnumResult Pausing = new CEnumResult (201);
private static readonly CEnumResult Dummy = new CEnumResult (msc_iUpdateNames);
protected CEnumResult () : base ()
{
}
protected CEnumResult (int i_iValue) : base (i_iValue)
{
}
protected override void CommonConstructor (int i_iValue)
{
base.CommonConstructor (i_iValue);
if (i_iValue == msc_iUpdateNames)
return;
if (this.GetType () == System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType)
ms_listoValue.Add (this);
}
public static new CEnumResult[] GetValues ()
{
List<CEnumResult> listoValue = new List<CEnumResult> ();
listoValue.AddRange (ms_listoValue);
return listoValue.ToArray ();
}
}
public class CEnumResultClassCommon : CEnumResult
{
private static List<CEnumResultClassCommon> ms_listoValue = new List<CEnumResultClassCommon>();
public static readonly CEnumResult Error_InternalProgramming = new CEnumResultClassCommon (1000);
public static readonly CEnumResult Error_Initialization = new CEnumResultClassCommon ();
public static readonly CEnumResult Error_ObjectNotInitialized = new CEnumResultClassCommon ();
public static readonly CEnumResult Error_DLLMissing = new CEnumResultClassCommon ();
// ... many more
private static readonly CEnumResult Dummy = new CEnumResultClassCommon (msc_iUpdateNames);
protected CEnumResultClassCommon () : base ()
{
}
protected CEnumResultClassCommon (int i_iValue) : base (i_iValue)
{
}
protected override void CommonConstructor (int i_iValue)
{
base.CommonConstructor (i_iValue);
if (i_iValue == msc_iUpdateNames)
return;
if (this.GetType () == System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType)
ms_listoValue.Add (this);
}
public static new CEnumResult[] GetValues ()
{
List<CEnumResult> listoValue = new List<CEnumResult> (CEnumResult.GetValues ());
listoValue.AddRange (ms_listoValue);
return listoValue.ToArray ();
}
}
The classes have been successfully tested with follwing code:
private static void Main (string[] args)
{
CEnumResult oEnumResult = CEnumResultClassCommon.Error_Initialization;
string sName = oEnumResult.Name; // sName = "Error_Initialization"
CEnum[] aoEnumResult = CEnumResultClassCommon.GetValues (); // aoEnumResult = {testCEnumResult.Program.CEnumResult[9]}
string[] asEnumNames = CEnum.GetNames (aoEnumResult);
int ixValue = Array.IndexOf (aoEnumResult, oEnumResult); // ixValue = 6
}
I realize I'm a bit late to this party, but here's my two cents.
We're all clear that Enum inheritance is not supported by the framework. Some very interesting workarounds have been suggested in this thread, but none of them felt quite like what I was looking for, so I had a go at it myself.
Introducing: ObjectEnum
You can check the code and documentation here: https://github.com/dimi3tron/ObjectEnum.
And the package here: https://www.nuget.org/packages/ObjectEnum
Or just install it: Install-Package ObjectEnum
In short, ObjectEnum<TEnum> acts as a wrapper for any enum. By overriding the GetDefinedValues() in subclasses, one can specify which enum values are valid for this specific class.
A number of operator overloads have been added to make an ObjectEnum<TEnum> instance behave as if it were an instance of the underlying enum, keeping in mind the defined value restrictions. This means you can easily compare the instance to an int or enum value, and thus use it in a switch case or any other conditional.
I'd like to refer to the github repo mentioned above for examples and further info.
I hope you find this useful. Feel free to comment or open an issue on github for further thoughts or comments.
Here are a few short examples of what you can do with ObjectEnum<TEnum>:
var sunday = new WorkDay(DayOfWeek.Sunday); //throws exception
var monday = new WorkDay(DayOfWeek.Monday); //works fine
var label = $"{monday} is day {(int)monday}." //produces: "Monday is day 1."
var mondayIsAlwaysMonday = monday == DayOfWeek.Monday; //true, sorry...
var friday = new WorkDay(DayOfWeek.Friday);
switch((DayOfWeek)friday){
case DayOfWeek.Monday:
//do something monday related
break;
/*...*/
case DayOfWeek.Friday:
//do something friday related
break;
}
Enums are not actual classes, even if they look like it. Internally, they are treated just like their underlying type (by default Int32). Therefore, you can only do this by "copying" single values from one enum to another and casting them to their integer number to compare them for equality.
Enums cannot be derrived from other enums, but only from int, uint, short, ushort, long, ulong, byte and sbyte.
Like Pascal said, you can use other enum's values or constants to initialize an enum value, but that's about it.
another possible solution:
public enum #base
{
x,
y,
z
}
public enum consume
{
x = #base.x,
y = #base.y,
z = #base.z,
a,b,c
}
// TODO: Add a unit-test to check that if #base and consume are aligned
HTH
This is not possible (as #JaredPar already mentioned). Trying to put logic to work around this is a bad practice. In case you have a base class that have an enum, you should list of all possible enum-values there, and the implementation of class should work with the values that it knows.
E.g. Supposed you have a base class BaseCatalog, and it has an enum ProductFormats (Digital, Physical). Then you can have a MusicCatalog or BookCatalog that could contains both Digital and Physical products, But if the class is ClothingCatalog, it should only contains Physical products.
The way you do this, if warranted, is to implement your own class structure that includes the features you wanted from your concept of an inherited enum, plus you can add more.
You simply implement equality comparators and functions to look up values you simply code yourself.
You make the constructors private and declare static instances of the class and any subclasses to whatever extent you want.
Or find a simple work around for your problem and stick with the native enum implementation.
Code Heavy Implementation of Inherited Enumerations:
/// <summary>
/// Generic Design for implementing inheritable enum
/// </summary>
public class ServiceBase
{
//members
protected int _id;
protected string _name;
//constructors
private ServiceBase(int id, string name)
{
_id = id;
_name = name;
}
//onlu required if subclassing
protected ServiceBase(int id, string name, bool isSubClass = true )
{
if( id <= _maxServiceId )
throw new InvalidProgramException("Bad Id in ServiceBase" );
_id = id;
_name = name;
}
//members
public int Id => _id;
public string Name => _name;
public virtual ServiceBase getService(int serviceBaseId)
{
return ALLBASESERVICES.SingleOrDefault(s => s.Id == _id);
}
//implement iComparable if required
//static methods
public static ServiceBase getServiceOrDefault(int serviceBaseId)
{
return SERVICE1.getService(serviceBaseId);
}
//Enumerations Here
public static ServiceBase SERVICE1 = new ServiceBase( 1, "First Service" );
public static ServiceBase SERVICE2 = new ServiceBase( 2, "Second Service" );
protected static ServiceBase[] ALLBASESERVICES =
{
//Enumerations list
SERVICE1,
SERVICE2
};
private static int _maxServiceId = ALLBASESERVICES.Max( s => s.Id );
//only required if subclassing
protected static ServiceBase[] combineServices(ServiceBase[] array1, ServiceBase[] array2)
{
List<ServiceBase> serviceBases = new List<ServiceBase>();
serviceBases.AddRange( array1 );
serviceBases.AddRange( array2 );
return serviceBases.ToArray();
}
}
/// <summary>
/// Generic Design for implementing inheritable enum
/// </summary>
public class ServiceJobs : ServiceBase
{
//constructor
private ServiceJobs(int id, string name)
: base( id, name )
{
_id = id;
_name = name;
}
//only required if subclassing
protected ServiceJobs(int id, string name, bool isSubClass = true )
: base( id, name )
{
if( id <= _maxServiceId )
throw new InvalidProgramException("Bad Id in ServiceJobs" );
_id = id;
_name = name;
}
//members
public override ServiceBase getService(int serviceBaseId)
{
if (ALLSERVICES == null)
{
ALLSERVICES = combineServices(ALLBASESERVICES, ALLJOBSERVICES);
}
return ALLSERVICES.SingleOrDefault(s => s.Id == _id);
}
//static methods
public static ServiceBase getServiceOrDefault(int serviceBaseId)
{
return SERVICE3.getService(serviceBaseId);
}
//sub class services here
public static ServiceBase SERVICE3 = new ServiceJobs( 3, "Third Service" );
public static ServiceBase SERVICE4 = new ServiceJobs( 4, "Forth Service" );
private static int _maxServiceId = ALLJOBSERVICES.Max( s => s.Id );
private static ServiceBase[] ALLJOBSERVICES =
{
//subclass service list
SERVICE3,
SERVICE4
};
//all services including superclass items
private static ServiceBase[] ALLSERVICES = null;
}
Note that you can use an enum instead of an int as the id, though the subclass will need a separate enum.
The enum class itself can be decorated with all kinds of flags, messages, functions etc.
A generic implementation would reduce a great deal of the code.
Depending on your situation you may NOT need derived Enums as they're based off System.Enum.
Take this code, you can pass in any Enum you like and get its selected value:
public CommonError FromErrorCode(Enum code)
{
Code = (int)Enum.Parse(code.GetType(), code.ToString());
You can perform inheritance in enum, however it's limited to following types only .
int, uint, byte, sbyte, short, ushort, long, ulong
E.g.
public enum Car:int{
Toyota,
Benz,
}

Difficulty to combine the use of base constructors and nonstatic fields

I was tackled by this issue for too many times so i decided to share and see what you guys think, lets look at the following (dumb) exemple:
public delegate void ToRun();
class Runner {
ToRun tr;
public Runner(ToRun f) {
tr=f;
}
public void run() {
tr();
}
}
class CountingRunner : Runner {
ToRun tr;
int i;
public CountingRunner(ToRun f) : base(f+=inc) {
i=0;
}
private static void inc() {
i++; //COMPILATION ERROR - i is not (and logically cannot be) static!
}
}
well, what i want to ask is:
Q1: why do base() parms have to be static?
Q2: what if, as in my exemple, we want to combine nonstatic fields or methods with the call to the base constructor? what is the most OOP way to do that?
Note : try not to give bandaid solutions like "just dont use the base c'tor", cause there might be more complex situation where using base is unavoidable, so im looking for a reasonable well designed solution for this.
Thanks!
Update:
my exemple was too easy to crack,therefore i feel like i havent learned enough, so lets try to give another (pretty dumb still) exemple:
public delegate int HashFunc<E>(E e);
public interface HashTable<E> {
void insert(E e);
bool isMember(E e);
}
class HashArray<E> : HashTable<E> where E : IComparable<E> {
private E[] a;
private bool[] taken;
public readonly int n;
public int size {
get { return n; }
}
HashFunc<E> hash;
public HashArray(int m , HashFunc<E> hash ) {
n=2*m;
a=new E[n];
taken=new bool[n];
for (int i=0 ; i<n ; i++) taken[i]=false;
this.hash=hash;
}
public void insert(E e) {
int index=hash(e),i;
for (i=index ; i<n && taken[i]!=false ; ++i) ;
if (i>=n)
for (i=0 ; i<index && taken[i]!=false ; ++i) ;
if (i>=index) return;
taken[i]=true;
a[i]=e;
}
public bool isMember(E e) {
int i=hash(e);
for ( ; i<n && taken[i]!=false && a[i].CompareTo(e)!=0 ; ++i );
if (i>=n || taken[i]==false) return false;
return true;
}
}
class HashArrayInt : HashArray<int> {
public HashArrayInt(int n) : base (n,HashFunc) {
}
public static int HashFunc(int i) {
return (i%n);// n is a non static field, every hash table has its own size!
}
}
in this exemple we are giving some weird implementation for an hash table where the hash function is unknown, and a special class for hash table of ints with predefined hash function, notice that here again we need to combine the non static size of the hashtable n and base c'tor...
Q1: why do base() parms have to be static?
They must be static because the instance hasn't been defined at the time of the constructor call (that definition was "in progress").
Q2: what if, as in my exemple, we want to combine nonstatic fields or methods with the call to the base constructor? what is the most OOP way to do that?
To OOP-way would is just simple method overrides.
class Runner
{
ToRun tr;
public Runner(ToRun f)
{
tr=f;
}
public virtual void Run()
{
tr();
}
}
class CountingRunner : Runner {
int i;
public CountingRunner(ToRun f) : base(f) {
i=0;
}
public override void Run() {
i++;
base.Run();
}
}
This is what you want:
class Runner {
protected event Action _toRun;
public Runner() {
}
public void Run() {
var r = _toRun;
if (r != null)
_toRun();
}
}
class CountingRunner : Runner {
int i;
public CountingRunner(Action f) : base() {
_toRun += f;
}
public void inc() {
i++;
}
}
EDIT
For your particular example with hash tables, this problem is solved by the design of the language. Just call GetHashCode() on the elements of your hashtable to determine their hashcode. You don't need implementations to pass a hashing function.
To answer your more general question of "How should I send functions manipulating instance data to the base class," you should either capture your instance variables in a lambda expression and send that to the base class, or consider a design in which the base class doesn't need access to the instance functions of its derived classes. I would go with the latter :)
One such design would be to have the function a pure virtual call in the base class. That would require derived classes to implement the virtual call in order to be instantiated. So here you would have a abstract int GetHashCode(E item) function in the base class, and just override it in your subclasses. Again, in this specific case the language does this for you with the virtual GetHashCode() function defined for all types.
Here is a non-abstract example (derived classes aren't required to override the hashing function).
class HashArray<E> : HashTable<E> where E : IComparable<E> {
private E[] a;
private bool[] taken;
public readonly int n;
public int size {
get { return n; }
}
public HashArray(int m) {
n=2*m;
a=new E[n];
taken=new bool[n];
for (int i=0 ; i<n ; i++) taken[i]=false;
}
public void insert(E e) {
int index= GetSpecialHashCode(e)%n;
int i;
for (i=index ; i<n && taken[i]!=false ; ++i) ;
if (i>=n)
for (i=0 ; i<index && taken[i]!=false ; ++i) ;
if (i>=index) return;
taken[i]=true;
a[i]=e;
}
public bool isMember(E e) {
int i= GetSpecialHashCode(e)%n;
for ( ; i<n && taken[i]!=false && a[i].CompareTo(e)!=0 ; ++i );
if (i>=n || taken[i]==false) return false;
return true;
}
protected virtual int GetSpecialHashCode(E item) {
return item.GetHashCode();
}
}
So you get a default hashcode generating function, but derived classes are also welcome to supply their own.
Regarding both Q1 and Q2, it's not that the parameters must be static, but rather the parameters must be accessible at the time they are invoked.
And base constructors are invoked prior to the local constructor, which is why you can't use this members as parameter for example, and why you shouldn't invoke virtual calls.
Not totally sure what the ultimate goal of that would be, but it does resemble a Decorator pattern.
For your last example, I think this could work:
class HashArrayInt : HashArray<int> {
public HashArrayInt(int n) : base (n,i => HashFunc(i,n)) {
}
private static int HashFunc(int i, int n) {
return (i%n);// n is a non static field, every hash table has its own size!
}
}
If not, you can do this:
class HashFuncProvider {
private int n;
public HashFuncProvider(int n){
this.n = n;
}
public int HashFunc(int i) {
return (i%n);
}
}
class HashArrayInt : HashArray<int> {
public HashArrayInt(int n) : base (n, new HashFuncProvider(n).HashFunc) {
}
}

Force C# Compiler to Create an Unused Object Instance

Yes exactly what I want to do :) At least for a particular class.
The problem is, I create a static instance of an object but I don not use it directly. Since I do some operations in the constructor ,like adding the object to a list, the constructor must be invoked at least once before I get the list.
I guess that the compiler just optimizes the unused object.
There must be a simple solution :-/
EDIT
Ok may be I miss something. Let me post my code. I wrote a class for custom enum purpose.
public class TypeSafeEnum<TNameType, TValueType>
{
protected readonly TNameType name;
protected readonly TValueType value;
private static List<TypeSafeEnum<TNameType, TValueType>> listEnums = new List<TypeSafeEnum<TNameType, TValueType>>();
protected TypeSafeEnum(TNameType name, TValueType value)
{
this.name = name;
this.value = value;
listEnums.Add(this);
}
public TNameType Name
{
get { return name; }
}
public TValueType Value
{
get { return value; }
}
public static TypeSafeEnum<TNameType, TValueType> GetName(TNameType name)
{
TypeSafeEnum<TNameType, TValueType> tse = null;
for (int i = 0; i < listEnums.Count; i++)
{
TypeSafeEnum<TNameType, TValueType> typeSafeEnum = listEnums[i];
if (EqualityComparer<TNameType>.Default.Equals(typeSafeEnum.name, name))
{
tse = typeSafeEnum;
}
}
return tse;
}
public static TypeSafeEnum<TNameType, TValueType> GetValue(TValueType value)
{
TypeSafeEnum<TNameType, TValueType> tse = null;
for (int i = 0; i < listEnums.Count; i++)
{
TypeSafeEnum<TNameType, TValueType> typeSafeEnum = listEnums[i];
if (EqualityComparer<TValueType>.Default.Equals(typeSafeEnum.value, value))
{
tse = typeSafeEnum;
}
}
return tse;
}
public static TNameType[] GetNames()
{
TNameType[] names = new TNameType[listEnums.Count];
for (int i = 0; i < listEnums.Count; i++)
{
TypeSafeEnum<TNameType, TValueType> typeSafeEnum = listEnums[i];
names[i] = typeSafeEnum.name;
}
return names;
}
public static TValueType[] GetValues()
{
TValueType[] values = new TValueType[listEnums.Count];
for (int i = 0; i < listEnums.Count; i++)
{
TypeSafeEnum<TNameType, TValueType> typeSafeEnum = listEnums[i];
values[i] = typeSafeEnum.value;
}
return values;
}
}
public abstract class StringEnum : TypeSafeEnum<string, int>
{
protected StringEnum(string name, int value) : base(name, value)
{
}
}
public sealed class FileOptionEnum : StringEnum
{
public static readonly FileOptionEnum Name = new FileOptionEnum("Name", 0);
public static readonly FileOptionEnum Extension = new FileOptionEnum("Extension", 1);
public static readonly FileOptionEnum Size = new FileOptionEnum("Size", 2);
public static readonly FileOptionEnum LastModified = new FileOptionEnum("Last Modified", 3);
public static readonly FileOptionEnum LastOpened = new FileOptionEnum("Last Opened", 4);
public static readonly FileOptionEnum Created = new FileOptionEnum("Created", 5);
public FileOptionEnum(string name, int value) : base(name, value)
{
}
}
Here is how I use it:
// if I omit this line it returns me empty array
FileOptionEnum #enum = FileOptionEnum.Name;
string[] names = FileOptionEnum.GetNames();
cbFileOptions.Items.AddRange(names);
You can simply write
new YourObject();
This will not be optimized away.
However, unless the class's constructor saves itself somewhere (eg, adding the object to list or static field, or adding an event handler to something else), the object will probably be garbage-collected right away.
First of all, please verify that the compiler indeed does optimize the code away. Chances are, it really doesn't: if your constructor call has side effects, the compiler doesn't really have the right to get rid of it.
And if it actually does get optimized away, you can use the GC.KeepAlive method to guarantee that the object remains:
GC.KeepAlive( new MyObj() );
This method doesn't really do anything - it has empty body. But it's special in a way that it can't be optimized out. So it you call it with some argument, then that argument also can't be optimized out.
Your idea will not work.
The static List<TypeSafeEnum<TNameType, TValueType>> listEnums field will be shared by all TypeSafeEnum classes that have the same name and value types.
To solve that problem, add a parameter for the actual enum class, like this:
public class TypeSafeEnum<TEnum, TName, TValue> where TEnum : TypeSafeEnum<TEnum, TName, TValue>
(You can then replace all of your TypeSafeEnum<...> fields and parameters with TEnum)
I'm pretty sure that this will also solve your actual question.
Since the base TypeSafeEnum class now references the inherited enum class, the inherited class' static constructor will run, initializing the values.
If you are just using some static functionality, why use an instance at all? Create a static class, and have a static 'Initialize()' method that you can call to set up your object.
Static members are not guaranteed to be initialized until you attempt to explicitly access them. You can get around this by creating an explicit static constructor (to avoid beforeFieldInit behavior) and explicitly access a static method (like a dummy Init method) to force static initialization.

Enum "Inheritance"

I have an enum in a low level namespace. I'd like to provide a class or enum in a mid level namespace that "inherits" the low level enum.
namespace low
{
public enum base
{
x, y, z
}
}
namespace mid
{
public enum consume : low.base
{
}
}
I'm hoping that this is possible, or perhaps some kind of class that can take the place of the enum consume which will provide a layer of abstraction for the enum, but still let an instance of that class access the enum.
Thoughts?
EDIT:
One of the reasons I haven't just switched this to consts in classes is that the low level enum is needed by a service that I must consume. I have been given the WSDLs and the XSDs, which define the structure as an enum. The service cannot be changed.
This is not possible. Enums cannot inherit from other enums. In fact all enums must actually inherit from System.Enum. C# allows syntax to change the underlying representation of the enum values which looks like inheritance, but in actuality they still inherit from System.enum.
See section 8.5.2 of the CLI spec for the full details. Relevant information from the spec
All enums must derive from System.Enum
Because of the above, all enums are value types and hence sealed
You can achieve what you want with classes:
public class Base
{
public const int A = 1;
public const int B = 2;
public const int C = 3;
}
public class Consume : Base
{
public const int D = 4;
public const int E = 5;
}
Now you can use these classes similar as when they were enums:
int i = Consume.B;
Update (after your update of the question):
If you assign the same int values to the constants as defined in the existing enum, then you can cast between the enum and the constants, e.g:
public enum SomeEnum // this is the existing enum (from WSDL)
{
A = 1,
B = 2,
...
}
public class Base
{
public const int A = (int)SomeEnum.A;
//...
}
public class Consume : Base
{
public const int D = 4;
public const int E = 5;
}
// where you have to use the enum, use a cast:
SomeEnum e = (SomeEnum)Consume.B;
The short answer is no. You can play a bit, if you want:
You can always do something like this:
private enum Base
{
A,
B,
C
}
private enum Consume
{
A = Base.A,
B = Base.B,
C = Base.C,
D,
E
}
But, it doesn't work all that great because Base.A != Consume.A
You can always do something like this, though:
public static class Extensions
{
public static T As<T>(this Consume c) where T : struct
{
return (T)System.Enum.Parse(typeof(T), c.ToString(), false);
}
}
In order to cross between Base and Consume...
You could also cast the values of the enums as ints, and compare them as ints instead of enum, but that kind of sucks too.
The extension method return should type cast it type T.
The solutions above using classes with int constants lack type-safety. I.e. you could invent new values actually not defined in the class.
Furthermore it is not possible for example to write a method taking one of these classes as input.
You would need to write
public void DoSomethingMeaningFull(int consumeValue) ...
However, there is a class based solution of the old days of Java, when there were no enums available. This provides an almost enum-like behaviour. The only caveat is that these constants cannot be used within a switch-statement.
public class MyBaseEnum
{
public static readonly MyBaseEnum A = new MyBaseEnum( 1 );
public static readonly MyBaseEnum B = new MyBaseEnum( 2 );
public static readonly MyBaseEnum C = new MyBaseEnum( 3 );
public int InternalValue { get; protected set; }
protected MyBaseEnum( int internalValue )
{
this.InternalValue = internalValue;
}
}
public class MyEnum : MyBaseEnum
{
public static readonly MyEnum D = new MyEnum( 4 );
public static readonly MyEnum E = new MyEnum( 5 );
protected MyEnum( int internalValue ) : base( internalValue )
{
// Nothing
}
}
[TestMethod]
public void EnumTest()
{
this.DoSomethingMeaningful( MyEnum.A );
}
private void DoSomethingMeaningful( MyBaseEnum enumValue )
{
// ...
if( enumValue == MyEnum.A ) { /* ... */ }
else if (enumValue == MyEnum.B) { /* ... */ }
// ...
}
Ignoring the fact that base is a reserved word you cannot do inheritance of enum.
The best thing you could do is something like that:
public enum Baseenum
{
x, y, z
}
public enum Consume
{
x = Baseenum.x,
y = Baseenum.y,
z = Baseenum.z
}
public void Test()
{
Baseenum a = Baseenum.x;
Consume newA = (Consume) a;
if ((Int32) a == (Int32) newA)
{
MessageBox.Show(newA.ToString());
}
}
Since they're all the same base type (ie: int) you could assign the value from an instance of one type to the other which a cast. Not ideal but it work.
This is what I did. What I've done differently is use the same name and the new keyword on the "consuming" enum. Since the name of the enum is the same, you can just mindlessly use it and it will be right. Plus you get intellisense. You just have to manually take care when setting it up that the values are copied over from the base and keep them sync'ed. You can help that along with code comments. This is another reason why in the database when storing enum values I always store the string, not the value. Because if you are using automatically assigned increasing integer values those can change over time.
// Base Class for balls
public class Ball
{
// keep synced with subclasses!
public enum Sizes
{
Small,
Medium,
Large
}
}
public class VolleyBall : Ball
{
// keep synced with base class!
public new enum Sizes
{
Small = Ball.Sizes.Small,
Medium = Ball.Sizes.Medium,
Large = Ball.Sizes.Large,
SmallMedium,
MediumLarge,
Ginormous
}
}
I know this answer is kind of late but this is what I ended up doing:
public class BaseAnimal : IEquatable<BaseAnimal>
{
public string Name { private set; get; }
public int Value { private set; get; }
public BaseAnimal(int value, String name)
{
this.Name = name;
this.Value = value;
}
public override String ToString()
{
return Name;
}
public bool Equals(BaseAnimal other)
{
return other.Name == this.Name && other.Value == this.Value;
}
}
public class AnimalType : BaseAnimal
{
public static readonly BaseAnimal Invertebrate = new BaseAnimal(1, "Invertebrate");
public static readonly BaseAnimal Amphibians = new BaseAnimal(2, "Amphibians");
// etc
}
public class DogType : AnimalType
{
public static readonly BaseAnimal Golden_Retriever = new BaseAnimal(3, "Golden_Retriever");
public static readonly BaseAnimal Great_Dane = new BaseAnimal(4, "Great_Dane");
// etc
}
Then I am able to do things like:
public void SomeMethod()
{
var a = AnimalType.Amphibians;
var b = AnimalType.Amphibians;
if (a == b)
{
// should be equal
}
// call method as
Foo(a);
// using ifs
if (a == AnimalType.Amphibians)
{
}
else if (a == AnimalType.Invertebrate)
{
}
else if (a == DogType.Golden_Retriever)
{
}
// etc
}
public void Foo(BaseAnimal typeOfAnimal)
{
}
Alternative solution
In my company, we avoid "jumping over projects" to get to non-common lower level projects. For instance, our presentation/API layer can only reference our domain layer, and the domain layer can only reference the data layer.
However, this is a problem when there are enums that need to be referenced by both the presentation and the domain layers.
Here is the solution that we have implemented (so far). It is a pretty good solution and works well for us. The other answers were hitting all around this.
The basic premise is that enums cannot be inherited - but classes can. So...
// In the lower level project (or DLL)...
public abstract class BaseEnums
{
public enum ImportanceType
{
None = 0,
Success = 1,
Warning = 2,
Information = 3,
Exclamation = 4
}
[Flags]
public enum StatusType : Int32
{
None = 0,
Pending = 1,
Approved = 2,
Canceled = 4,
Accepted = (8 | Approved),
Rejected = 16,
Shipped = (32 | Accepted),
Reconciled = (64 | Shipped)
}
public enum Conveyance
{
None = 0,
Feet = 1,
Automobile = 2,
Bicycle = 3,
Motorcycle = 4,
TukTuk = 5,
Horse = 6,
Yak = 7,
Segue = 8
}
Then, to "inherit" the enums in another higher level project...
// Class in another project
public sealed class SubEnums: BaseEnums
{
private SubEnums()
{}
}
This has three real advantages...
The enum definitions are automatically the same in both projects - by
definition.
Any changes to the enum definitions are automatically
echoed in the second without having to make any modifications to the
second class.
The enums are based on the same code - so the values can easily be compared (with some caveats).
To reference the enums in the first project, you can use the prefix of the class: BaseEnums.StatusType.Pending or add a "using static BaseEnums;" statement to your usings.
In the second project when dealing with the inherited class however, I could not get the "using static ..." approach to work, so all references to the "inherited enums" would be prefixed with the class, e.g. SubEnums.StatusType.Pending. If anyone comes up with a way to allow the "using static" approach to be used in the second project, let me know.
I am sure that this can be tweaked to make it even better - but this actually works and I have used this approach in working projects.
I also wanted to overload Enums and created a mix of the answer of 'Seven' on this page and the answer of 'Merlyn Morgan-Graham' on a duplicate post of this, plus a couple of improvements.
Main advantages of my solution over the others:
automatic increment of the underlying int value
automatic naming
This is an out-of-the-box solution and may be directly inserted into your project. It is designed to my needs, so if you don't like some parts of it, just replace them with your own code.
First, there is the base class CEnum that all custom enums should inherit from. It has the basic functionality, similar to the .net Enum type:
public class CEnum
{
protected static readonly int msc_iUpdateNames = int.MinValue;
protected static int ms_iAutoValue = -1;
protected static List<int> ms_listiValue = new List<int>();
public int Value
{
get;
protected set;
}
public string Name
{
get;
protected set;
}
protected CEnum ()
{
CommonConstructor (-1);
}
protected CEnum (int i_iValue)
{
CommonConstructor (i_iValue);
}
public static string[] GetNames (IList<CEnum> i_listoValue)
{
if (i_listoValue == null)
return null;
string[] asName = new string[i_listoValue.Count];
for (int ixCnt = 0; ixCnt < asName.Length; ixCnt++)
asName[ixCnt] = i_listoValue[ixCnt]?.Name;
return asName;
}
public static CEnum[] GetValues ()
{
return new CEnum[0];
}
protected virtual void CommonConstructor (int i_iValue)
{
if (i_iValue == msc_iUpdateNames)
{
UpdateNames (this.GetType ());
return;
}
else if (i_iValue > ms_iAutoValue)
ms_iAutoValue = i_iValue;
else
i_iValue = ++ms_iAutoValue;
if (ms_listiValue.Contains (i_iValue))
throw new ArgumentException ("duplicate value " + i_iValue.ToString ());
Value = i_iValue;
ms_listiValue.Add (i_iValue);
}
private static void UpdateNames (Type i_oType)
{
if (i_oType == null)
return;
FieldInfo[] aoFieldInfo = i_oType.GetFields (BindingFlags.Public | BindingFlags.Static);
foreach (FieldInfo oFieldInfo in aoFieldInfo)
{
CEnum oEnumResult = oFieldInfo.GetValue (null) as CEnum;
if (oEnumResult == null)
continue;
oEnumResult.Name = oFieldInfo.Name;
}
}
}
Secondly, here are 2 derived Enum classes. All derived classes need some basic methods in order to work as expected. It's always the same boilerplate code; I haven't found a way yet to outsource it to the base class. The code of the first level of inheritance differs slightly from all subsequent levels.
public class CEnumResult : CEnum
{
private static List<CEnumResult> ms_listoValue = new List<CEnumResult>();
public static readonly CEnumResult Nothing = new CEnumResult ( 0);
public static readonly CEnumResult SUCCESS = new CEnumResult ( 1);
public static readonly CEnumResult UserAbort = new CEnumResult ( 11);
public static readonly CEnumResult InProgress = new CEnumResult (101);
public static readonly CEnumResult Pausing = new CEnumResult (201);
private static readonly CEnumResult Dummy = new CEnumResult (msc_iUpdateNames);
protected CEnumResult () : base ()
{
}
protected CEnumResult (int i_iValue) : base (i_iValue)
{
}
protected override void CommonConstructor (int i_iValue)
{
base.CommonConstructor (i_iValue);
if (i_iValue == msc_iUpdateNames)
return;
if (this.GetType () == System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType)
ms_listoValue.Add (this);
}
public static new CEnumResult[] GetValues ()
{
List<CEnumResult> listoValue = new List<CEnumResult> ();
listoValue.AddRange (ms_listoValue);
return listoValue.ToArray ();
}
}
public class CEnumResultClassCommon : CEnumResult
{
private static List<CEnumResultClassCommon> ms_listoValue = new List<CEnumResultClassCommon>();
public static readonly CEnumResult Error_InternalProgramming = new CEnumResultClassCommon (1000);
public static readonly CEnumResult Error_Initialization = new CEnumResultClassCommon ();
public static readonly CEnumResult Error_ObjectNotInitialized = new CEnumResultClassCommon ();
public static readonly CEnumResult Error_DLLMissing = new CEnumResultClassCommon ();
// ... many more
private static readonly CEnumResult Dummy = new CEnumResultClassCommon (msc_iUpdateNames);
protected CEnumResultClassCommon () : base ()
{
}
protected CEnumResultClassCommon (int i_iValue) : base (i_iValue)
{
}
protected override void CommonConstructor (int i_iValue)
{
base.CommonConstructor (i_iValue);
if (i_iValue == msc_iUpdateNames)
return;
if (this.GetType () == System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType)
ms_listoValue.Add (this);
}
public static new CEnumResult[] GetValues ()
{
List<CEnumResult> listoValue = new List<CEnumResult> (CEnumResult.GetValues ());
listoValue.AddRange (ms_listoValue);
return listoValue.ToArray ();
}
}
The classes have been successfully tested with follwing code:
private static void Main (string[] args)
{
CEnumResult oEnumResult = CEnumResultClassCommon.Error_Initialization;
string sName = oEnumResult.Name; // sName = "Error_Initialization"
CEnum[] aoEnumResult = CEnumResultClassCommon.GetValues (); // aoEnumResult = {testCEnumResult.Program.CEnumResult[9]}
string[] asEnumNames = CEnum.GetNames (aoEnumResult);
int ixValue = Array.IndexOf (aoEnumResult, oEnumResult); // ixValue = 6
}
I realize I'm a bit late to this party, but here's my two cents.
We're all clear that Enum inheritance is not supported by the framework. Some very interesting workarounds have been suggested in this thread, but none of them felt quite like what I was looking for, so I had a go at it myself.
Introducing: ObjectEnum
You can check the code and documentation here: https://github.com/dimi3tron/ObjectEnum.
And the package here: https://www.nuget.org/packages/ObjectEnum
Or just install it: Install-Package ObjectEnum
In short, ObjectEnum<TEnum> acts as a wrapper for any enum. By overriding the GetDefinedValues() in subclasses, one can specify which enum values are valid for this specific class.
A number of operator overloads have been added to make an ObjectEnum<TEnum> instance behave as if it were an instance of the underlying enum, keeping in mind the defined value restrictions. This means you can easily compare the instance to an int or enum value, and thus use it in a switch case or any other conditional.
I'd like to refer to the github repo mentioned above for examples and further info.
I hope you find this useful. Feel free to comment or open an issue on github for further thoughts or comments.
Here are a few short examples of what you can do with ObjectEnum<TEnum>:
var sunday = new WorkDay(DayOfWeek.Sunday); //throws exception
var monday = new WorkDay(DayOfWeek.Monday); //works fine
var label = $"{monday} is day {(int)monday}." //produces: "Monday is day 1."
var mondayIsAlwaysMonday = monday == DayOfWeek.Monday; //true, sorry...
var friday = new WorkDay(DayOfWeek.Friday);
switch((DayOfWeek)friday){
case DayOfWeek.Monday:
//do something monday related
break;
/*...*/
case DayOfWeek.Friday:
//do something friday related
break;
}
Enums are not actual classes, even if they look like it. Internally, they are treated just like their underlying type (by default Int32). Therefore, you can only do this by "copying" single values from one enum to another and casting them to their integer number to compare them for equality.
Enums cannot be derrived from other enums, but only from int, uint, short, ushort, long, ulong, byte and sbyte.
Like Pascal said, you can use other enum's values or constants to initialize an enum value, but that's about it.
another possible solution:
public enum #base
{
x,
y,
z
}
public enum consume
{
x = #base.x,
y = #base.y,
z = #base.z,
a,b,c
}
// TODO: Add a unit-test to check that if #base and consume are aligned
HTH
This is not possible (as #JaredPar already mentioned). Trying to put logic to work around this is a bad practice. In case you have a base class that have an enum, you should list of all possible enum-values there, and the implementation of class should work with the values that it knows.
E.g. Supposed you have a base class BaseCatalog, and it has an enum ProductFormats (Digital, Physical). Then you can have a MusicCatalog or BookCatalog that could contains both Digital and Physical products, But if the class is ClothingCatalog, it should only contains Physical products.
The way you do this, if warranted, is to implement your own class structure that includes the features you wanted from your concept of an inherited enum, plus you can add more.
You simply implement equality comparators and functions to look up values you simply code yourself.
You make the constructors private and declare static instances of the class and any subclasses to whatever extent you want.
Or find a simple work around for your problem and stick with the native enum implementation.
Code Heavy Implementation of Inherited Enumerations:
/// <summary>
/// Generic Design for implementing inheritable enum
/// </summary>
public class ServiceBase
{
//members
protected int _id;
protected string _name;
//constructors
private ServiceBase(int id, string name)
{
_id = id;
_name = name;
}
//onlu required if subclassing
protected ServiceBase(int id, string name, bool isSubClass = true )
{
if( id <= _maxServiceId )
throw new InvalidProgramException("Bad Id in ServiceBase" );
_id = id;
_name = name;
}
//members
public int Id => _id;
public string Name => _name;
public virtual ServiceBase getService(int serviceBaseId)
{
return ALLBASESERVICES.SingleOrDefault(s => s.Id == _id);
}
//implement iComparable if required
//static methods
public static ServiceBase getServiceOrDefault(int serviceBaseId)
{
return SERVICE1.getService(serviceBaseId);
}
//Enumerations Here
public static ServiceBase SERVICE1 = new ServiceBase( 1, "First Service" );
public static ServiceBase SERVICE2 = new ServiceBase( 2, "Second Service" );
protected static ServiceBase[] ALLBASESERVICES =
{
//Enumerations list
SERVICE1,
SERVICE2
};
private static int _maxServiceId = ALLBASESERVICES.Max( s => s.Id );
//only required if subclassing
protected static ServiceBase[] combineServices(ServiceBase[] array1, ServiceBase[] array2)
{
List<ServiceBase> serviceBases = new List<ServiceBase>();
serviceBases.AddRange( array1 );
serviceBases.AddRange( array2 );
return serviceBases.ToArray();
}
}
/// <summary>
/// Generic Design for implementing inheritable enum
/// </summary>
public class ServiceJobs : ServiceBase
{
//constructor
private ServiceJobs(int id, string name)
: base( id, name )
{
_id = id;
_name = name;
}
//only required if subclassing
protected ServiceJobs(int id, string name, bool isSubClass = true )
: base( id, name )
{
if( id <= _maxServiceId )
throw new InvalidProgramException("Bad Id in ServiceJobs" );
_id = id;
_name = name;
}
//members
public override ServiceBase getService(int serviceBaseId)
{
if (ALLSERVICES == null)
{
ALLSERVICES = combineServices(ALLBASESERVICES, ALLJOBSERVICES);
}
return ALLSERVICES.SingleOrDefault(s => s.Id == _id);
}
//static methods
public static ServiceBase getServiceOrDefault(int serviceBaseId)
{
return SERVICE3.getService(serviceBaseId);
}
//sub class services here
public static ServiceBase SERVICE3 = new ServiceJobs( 3, "Third Service" );
public static ServiceBase SERVICE4 = new ServiceJobs( 4, "Forth Service" );
private static int _maxServiceId = ALLJOBSERVICES.Max( s => s.Id );
private static ServiceBase[] ALLJOBSERVICES =
{
//subclass service list
SERVICE3,
SERVICE4
};
//all services including superclass items
private static ServiceBase[] ALLSERVICES = null;
}
Note that you can use an enum instead of an int as the id, though the subclass will need a separate enum.
The enum class itself can be decorated with all kinds of flags, messages, functions etc.
A generic implementation would reduce a great deal of the code.
Depending on your situation you may NOT need derived Enums as they're based off System.Enum.
Take this code, you can pass in any Enum you like and get its selected value:
public CommonError FromErrorCode(Enum code)
{
Code = (int)Enum.Parse(code.GetType(), code.ToString());
You can perform inheritance in enum, however it's limited to following types only .
int, uint, byte, sbyte, short, ushort, long, ulong
E.g.
public enum Car:int{
Toyota,
Benz,
}

Categories