Ayende @ Rahien

Hi!
My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:

ayende@ayende.com

+972 52-548-6969

, @ Q c

Posts: 5,972 | Comments: 44,523

filter by tags archive

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

Niki

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) {

  if (layer == FIRST && type != WorkType.COLLECTION) return true;

  return layer == SECOND && type == WorkType.COLLECTION;

}

}

I know it's not the same internally, but the syntax would be more or less the same.

Ayende Rahien

Java enums also have state, which extension methods do not have.

Hendry Luk

Having said that, there's nothing stopping us from implementing it the same way as java counterpart:

private static class Layer

{

 public static readonly Layer FIRST = new Layer();

 public static readonly Layer SECOND = new Layer();


public boolean IsRightLayer(WorkType type) {

    if (this == FIRST && type != WorkType.COLLECTION) return true;

    return this == SECOND && type == WorkType.COLLECTION;

}

}

David

How about using extension methods?

public static class LayerExtensions

{

public static bool IsRightLayer(this Layer layer, WorkType workType)

{

if (layer == Layer.FIRST && workType != WorkType.COLLECTION) return true;

return layer == Layer.SECOND && workType == WorkType.COLLECTION;

}

}

David

Oops, shoulda refreshed before posting :-\

Matthew Podwysocki

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) =

  match (x, workType) with

  | l, w when l = First && w <> Collection -> true

  | l, w -> l = Second && w = Collection

Then I can use it such as this:

let result = Layer.Second.IsRightLayer(WorkType.Collection)

Matt

Justin Rudd

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.

Andrey Shchekin

Good choice. Enums are antipattern for most situations anyway, since they lead to having unextensible switch-by-enum instead of using polymorphism.

Mike Brown

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;

Mike Brown

Just realized that my code got mangled by html

private readonly Func<WorkType,bool> isRightLayer;

Fred Hirschfeld

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

{

[PlanetMeasurements(3.303e+23, 2.4397e6)]

Mercury,


[PlanetMeasurements(4.869e+24, 6.0518e6)]

Venus

}

Then in the extension methods you would simply access these attributes and use their values thus eliminating the need for the switch statements.

Ayende Rahien

This code is for the .NET 2.0, no Func

Germ&#225;n Schuager

How would you map a class with a property of such "enum" type in NHibernate?

Comment preview

Comments have been closed on this topic.

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. Production postmortem (5):
    29 Jul 2015 - The evil licensing code
  2. Career planning (6):
    24 Jul 2015 - The immortal choices aren't
  3. API Design (7):
    20 Jul 2015 - We’ll let the users sort it out
  4. What is new in RavenDB 3.5 (3):
    15 Jul 2015 - Exploring data in the dark
  5. The RavenDB Comic Strip (3):
    28 May 2015 - Part III – High availability & sleeping soundly
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats