Related
Following How to decorate code in C# wiithout C/C++ - like macros I have just switched my logging system over to accept log messages as lambdas rather than as strings:
void Log(Func<string> msg)
{
if (logIsEnabled)
{
Debug.Write(msg());
}
}
My understanding is that this is much better, performance-wise, in that if I write:
Log(() => "foo(" + myInteger + ")");
then the string foo(42) is constructed only if logIsEnabled. For the sake of this question, let's assume that Log() is being called at high frequency, and constructing these strings for the log comes at an undesirable cost.
Suddenly I worried, though - is a lambda being instantiated every time this line of code is reached? Might that be more of a performance cost than constructing a string? I'm not clear on what's happening here, under the hood.
So, my question is: how is the lambda actually implemented? Is it constructed at compile-time and passed just as a pointer to a function? Is it constructed on first use and on subsequent passes just a pointer? Or is it constructed every time the line of code executes?
is a lambda being instantiated every time this line of code is reached?
Yes. Not only a new Func<string> is instantiated every time, but also a small compiler-generated class. Let's post some code to SharpLab, and see what comes out:
using System;
class Program
{
static bool logIsEnabled;
static void Main()
{
logIsEnabled = true;
int myInteger = 13;
Log(() => "foo(" + myInteger + ")");
}
static void Log(Func<string> msg)
{
if (logIsEnabled)
{
Console.WriteLine(msg());
}
}
}
SharpLab output (sanitized):
using System;
using System.Runtime.CompilerServices;
internal class Program
{
[CompilerGenerated]
private sealed class DisplayClass
{
public int myInteger;
internal string M()
{
return string.Concat("foo(", myInteger.ToString(), ")");
}
}
private static bool logIsEnabled;
private static void Main()
{
DisplayClass displayClass = new DisplayClass();
logIsEnabled = true;
displayClass.myInteger = 13;
Log(new Func<string>(displayClass.M));
}
private static void Log(Func<string> msg)
{
if (logIsEnabled)
{
Console.WriteLine(msg());
}
}
}
The DisplayClass is the closure that the compiler had to generate, in order to hold the myInteger variable. This variable is hoisted to a public field of the DisplayClass class.
The Visual Studio can help you at detecting that a variable has been captured. Just hover the mouse over the lambda operator (=>).
It is possible to avoid the allocation of the two objects by passing the myInteger as an argument, instead of relying on the convenience of captured variables and closures. Here is how:
using System;
class Program
{
static bool logIsEnabled;
static void Main()
{
logIsEnabled = true;
int myInteger = 13;
Log(arg => "foo(" + arg + ")", myInteger);
}
static void Log<TArg>(Func<TArg, string> msg, TArg arg)
{
if (logIsEnabled)
{
Console.WriteLine(msg(arg));
}
}
}
SharpLab output (sanitized):
using System;
using System.Runtime.CompilerServices;
internal class Program
{
[Serializable]
[CompilerGenerated]
private sealed class C
{
public static readonly C singleton = new C();
public static Func<int, string> lambda;
internal string M(int arg)
{
return string.Concat("foo(", arg.ToString(), ")");
}
}
private static bool logIsEnabled;
private static void Main()
{
logIsEnabled = true;
int arg = 13;
Log(C.lambda ?? (C.lambda = new Func<int, string>(C.singleton.M)), arg);
}
private static void Log<TArg>(Func<TArg, string> msg, TArg arg)
{
if (logIsEnabled)
{
Console.WriteLine(msg(arg));
}
}
}
Now the compiler generated a singleton (the C class), and the Func<TArg, string> is instantiated only once per TArg type. So if your program uses the Log<TArg> with ints, strings and decimals, only a Func<int, string>, a Func<string, string> and a Func<decimal, string> will be created in total, irrespective of how many times the Log<TArg> will be invoked.
In case you want to pass more than one arguments to the Log method, you'll have to write additional Log<TArg1, TArg2>, Log<TArg1, TArg2, TArg3> etc overloads.
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,
}
I'm used to programming in Java however for this project I'm supposed to be using C#, I'm trying to convert my Packet system over from my Java project, however I'm running into some issues using the C# Compiler. Here's the code.
abstract class Packet
{
public static enum PacketTypes
{
INVALID(-1), LOGIN(00);
private int packetId;
private PacketTypes(int packetId)
{
this.packetId = packetId;
}
public int getId() { return packetId; }
}
}
This is actually exactly how it's done in my Java Code, and I have the individual packets extend the Packet class. I'm trying to figure out how to make this all come together in C#. Perhaps having a separate class for each packet isn't the way it should be done here?
I'm not sure what you're trying to achieve, but you can set values for particular enum elements in C#:
public enum PacketTypes
{
INVALID = -1;
LOGIN = 0;
}
Because enum is by default backed by int, you can cast it from/to int without additional code.
enums in C# cannot content any members, so you can't add methods/properties/fields to enum declaration.
Unlike Java where enums are classes, in C# enums are plain values. They cannot have member functions or fields.
One approach that could help is to define an extension method for your enum, like this:
public static class PacketTypesExtensions {
static readonly IDictionary<PacketTypes,int> IdForType = new Dictionary<PacketTypes,int> {
{ PacketTypes.INVALID, -1 }
, { PacketTypes.LOGIN, 0 }
};
static readonly IDictionary<PacketTypes,string> DescrForType = new Dictionary<PacketTypes,string> {
{ PacketTypes.INVALID, "<invalid packet type>" }
, { PacketTypes.LOGIN, "<user login>" }
};
public static string Description(this PacketTypes t) {
return DescrForType[t];
}
public static int Id(this PacketTypes t) {
return IdForType[t];
}
}
This lets you keep Java syntax:
PacketTypes pt = ... // <<== Assign a packet type here
int id = pt.Id(); // This calls the static extension method
string d = pt.Description();
You could try this in addition to Marcins answer.
public enum PacketTypes
{
INVALID = -1;
LOGIN = 0;
}
public class Packet
{
public PacketTypes PacketType { get; set;}
}
In your code somewhere, you would do this
public void DoSomething()
{
var packet = new Packet();
packet.PacketType = PacketTypes.INVALID; // Assign packtype
Console.WriteLine(packet.PacketType.ToString()); // Retrieve and print
}
Lets suppose we have these classes:
class A {
public string attr = "Class A";
public static void getAttribute(){
self currentClass = new self(); // equivalent to php
Console.Write("Attribute : " + currentClass.attr);
}
}
Class B : A {
public string attr = "Class B";
}
B = new B();
B.getAttribute();
I want B.getAttribute(); to print Attribute: Class B. How can I do this?
This is fundamentally impossible.
B.getAttribute() compiles to A.getAttribute().
I probably know what you are trying to do, but I have to tell you that this kind of PHP approach makes no sense in C#. I discourage you from using it.
public class A
{
private String attr = "Class A";
public static String getAttribute()
{
return (new A()).attr;
}
}
public class B : A
{
private String attr = "Class B";
public static String getAttribute()
{
return (new B()).attr;
}
}
You get the current class instance by the 'this' keyword. Obviously you cannot access that in a static method since by definition a static method executes without the context of a particular instance.
On the other hand, to access a member variable/property/method from inside the same class, you don't need the 'this' keyword at all, since it's implicit.
If you're asking how to do something like that in C#, I think the answer would be along these lines:
public class A
{
public virtual string attr
{
get { return "Class A" }
}
public void getAttribute(){
Console.Write("Attribute : " + attr);
}
}
public class B : A
{
public override string attr
{
get { return "Class B"; }
}
}
var b = new B();
b.getAttribute();
Regarding my comment in the other answer, if you needed getAttribute to be static, you could implement it this way:
public static void getAttribute(A obj){
Console.Write("Attribute : " + obj.attr);
}
You would then call it like this:
var b = new B();
A.getAttribute(b);
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,
}