Emulating Java Enums
Java Enums are much more powerful than the ones that exists in the CLR. There are numerous ways of handling this issue, but here is my approach.
Given this enum (defined in Java):
private static enum Layer { FIRST, SECOND; public boolean isRightLayer(WorkType type) { if (this == FIRST && type != WorkType.COLLECTION) return true; return this == SECOND && type == WorkType.COLLECTION; } }
And the C# version is:
private class Layer { public static readonly Layer First = new Layer(delegate(WorkType type) { return type != WorkType.Collection; }); public static readonly Layer Second = new Layer(delegate(WorkType type) { return type == WorkType.Collection; }); public delegate bool IsRightLayerDelegate(WorkType type); private readonly IsRightLayerDelegate isRightLayer; protected Layer(IsRightLayerDelegate isRightLayer) { this.isRightLayer = isRightLayer; } public bool IsRightLayer(WorkType type) { return isRightLayer(type); } }
Comments
Why don't you just declare an extension method on you enum?
private static enum Layer { FIRST, SECOND }
private static class LayerExtensions {
public static bool isRightLayer(this Layer layer, WorkType type) {
}
}
I know it's not the same internally, but the syntax would be more or less the same.
Java enums also have state, which extension methods do not have.
Having said that, there's nothing stopping us from implementing it the same way as java counterpart:
private static class Layer
{
}
}
How about using extension methods?
public static class LayerExtensions
{
public static bool IsRightLayer(this Layer layer, WorkType workType)
{
}
}
Oops, shoulda refreshed before posting :-\
This is why I like F# for this purpose using discriminated unions. Such code as this works perfectly for modeling what was above:
light
type WorkType =
| Collection
| NonCollection
type Layer =
| First
| Second
with member x.IsRightLayer(workType) =
Then I can use it such as this:
let result = Layer.Second.IsRightLayer(WorkType.Collection)
Matt
The C# enum isn't quite a replacement for the Java one.
As it is, it can't be serialized. Adding serializable is just one part. You'd also have to implement whatever the equivalent of readObject and writeObject are to ensure the same instance is returned no matter what.
It can't be used in a switch statement.
You could use the same delegate trick to add methods to get polymorphism like you can with Java enums ( http://langrsoft.com/articles/enum2.shtml), but that breaks down pretty quick if you get beyond a few methods.
I'm a big fan of Java enums and I had a look at emulating their functionality a while ago in both C# 2.0 and C# 3.5:
siliconbea.ch/.../emulating-java-5-enums-in-dotnet
My C# 2.0 solution uses an inner enum and a class that wraps it (with common functionality in a base class).
siliconbea.ch/.../emulating-java-5-enums-in-dot...
My C# 3.5 solution uses extension methods.
Good choice. Enums are antipattern for most situations anyway, since they lead to having unextensible switch-by-enum instead of using polymorphism.
Quick question. What are your thoughts on using the Func <t derivatives for delegate declaration?
So instead of:
public delegate bool IsRightLayerDelegate(WorkType type);
private readonly IsRightLayerDelegate isRightLayer;
You just have
private Func <worktype,bool> isRightLayer;
Just realized that my code got mangled by html
private readonly Func<WorkType,bool> isRightLayer;
Bruce,
The extension version looks very nice and you could improve it slightly by adding a custom attribute to the code that would decorate the enum member:
public enum Planet
{
}
Then in the extension methods you would simply access these attributes and use their values thus eliminating the need for the switch statements.
This code is for the .NET 2.0, no Func <t>
How would you map a class with a property of such "enum" type in NHibernate?
Comment preview