9

In most popular programming languages like Java and C# there is a way to define enums, which are essentially datatypes with a fixed set of values, e.g. DayOfWeek.

The problem is, given a value, e.g. DayOfWeek.Monday, how do I get the next value of the enum, in this particular case DayOfWeek.Tuesday?

I realize that not all enums are ordered and there might be different kinds of orders for them (cyclic, partial etc.), but a simple next operation would be sufficient in most cases. In fact, since the set of values in a enum is fixed and limited, this could be done completely declaratively, assuming there is a means in the language to do so. However in most programming languages that is simply not possible, at least not as easily as it could be in theory.

So, my question is: why is that so? What are the reasons for not providing a simple syntax for declaring the next value for a enum? I suggest, in C# or Java this could even be done with a special attribute or annotation, resp. But there are none, as far as I know.

I am explicitly not asking for workarounds; I know that there are alternative solutions. I just want to know why I have to employ a workaround in the first place.

12
  • 2
    for exactly the reason you stated, if the programmer wanted a next then he should have provided one Jul 8, 2014 at 8:59
  • I challenge your statement that a simple next operation would be sufficient (or even applicable) in most cases. Perhaps it's been applicable to in most of your cases so far, but keep in mind that software (and enums) can model any number of abstract concepts. This one comes to mind thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx.
    – MetaFight
    Jul 8, 2014 at 9:04
  • 3
    I would argue that this type of situation comes up rarely, like when you're dealing with days of the week or months of the year. In most cases, including uses of enum as flags, you don't need to know what order or what value they hold in order to program something using it properly.
    – Neil
    Jul 8, 2014 at 9:24
  • 1
    @proskor It is important to make the distinction between dealing with enum numerical equivalent and order. Due to the lack of direct support in Java and in most languages, it could be said that enums aren't meant to give too much importance to this. For example, if it is Monday, and I wanted to know what the next day is, I'd convert to day of the year, and then add one to it. If you then need the day of the week, you should convert back. Consider also that not everywhere in the world uses the days of the week as we know them, thus maybe a better system would be appropriate.
    – Neil
    Jul 8, 2014 at 10:49
  • 1
    Java could've gotten enums "for free" if it supported algebraic data types or encapsulating values that aren't records (which are what Java classes are.) But it doesn't, so adding enums required special work from the part of the designers, and they have certain limitations as a result. They could add syntax sugar for a next function, but that'd require even more work on their part, and it's kind of a slipper slope; you could keep asking for more and more features until they have to add full algebraic data types to the language.
    – Doval
    Jul 8, 2014 at 12:08

9 Answers 9

11

Why isn't there a next operation on enums?

It is difficult to generalize.

It is an decision made by each programming language designer / team. But note that some programming languages do provide a "next" operation for enumerated types.

In Pascal, the succ function returns the next value of an enumerated type, and the pred function returns the previous value. But this only works for classic enumerated types. C-style enumerated types have "holes" in the type domain, and the succ and pred functions are not allowed.

Reference: http://www.freepascal.org/docs-html/ref/refse12.html#QQ2-27-32

And, in fact, that gives a clue as to why many languages with enumeration / enumerated types don't have a "next" operation. It is prohibitively expensive when you can't implement "next" by using integer addition under the hood.


Of course, in the languages that don't support next directly, it is always possible to implement it for yourself ... if you need it ... as some kind of helper method / function.

11

In Java, the enum is a reference type (don't let that little 'e' fool you). You can do neat things with it like define methods. A classic example of that is the Operation enum being defined as:

public enum Operation {
  PLUS   { double eval(double x, double y) { return x + y; } },
  MINUS  { double eval(double x, double y) { return x - y; } },
  TIMES  { double eval(double x, double y) { return x * y; } },
  DIVIDE { double eval(double x, double y) { return x / y; } };

  // Do arithmetic op represented by this constant
  abstract double eval(double x, double y);
}
//Elsewhere:
Operation op = Operation.PLUS;
double two = op.eval(1, 1);

And you can see... yep, it has methods and so its not a primitive. They are Objects.

There is also some magic that happens in the compiler as described in the Java Enum Tutorial:

The compiler automatically adds some special methods when it creates an enum. For example, they have a static values method that returns an array containing all of the values of the enum in the order they are declared. This method is commonly used in combination with the for-each construct to iterate over the values of an enum type. For example, this code from the Planet class example below iterates over all the planets in the solar system.

And I'll certainly agree that its annoying that this isn't mentioned in the javadocs.

The values that are returned from the values() call is an array that one can then iterate over.

class Demo {
    enum DayOfWeek {
        U, M, T, W, R, F, S
    }

    public static void main (String[] args) {
        for (DayOfWeek day : DayOfWeek.values()) {
            System.out.println(day.toString());
        }
    }
}

This prints out:

U
M
T
W
R
F
S

Run this code at ideone

Why no next? Well, given the ability to get the values() array it fills all the use cases for the next() method and is a bit more powerful.

If you really do want the next() method it takes takes a little bit of a hoop to get the array into an Iterator object (which is itself a replacement for the Enumeration type - see the javadoc):

import java.util.*;

class Demo {
    enum DayOfWeek {
        U, M, T, W, R, F, S
    }

    public static void main (String[] args) {
        Iterator days = Arrays.asList(DayOfWeek.values()).iterator();
        while(days.hasNext()) {
            System.out.println(days.next());
        }
    }
}

Run this code at ideone

So again, the reason that its not there is that its not needed. You can get an array back from the enum quite easily and iterate over that, or convert that array into an Iterator allowing you to call next().

There is also possibly the confusion that would be had trying to make the enum and Enumeration look too similar (they already look too similar) and trying to make the enum look more like the Enumeration with the same method calls would further confuse things. That said, this is just speculation.

Fundamentally, the Java enum is much like the C enum with the ability to have some methods on the side. Its a bit more constrained you can't have them be specific numbers behind the scenes as you can in C:

/* This is C */
enum cardsuit {
    CLUBS    = 1,
    DIAMONDS = 2,
    HEARTS   = 4,
    SPADES   = 8
};

People sometimes point to Pascal and say succ can be called on an enum there, why not in Java? Pascal enums are ordinal types while C enums are not. Java borrows from C rather than Pascal.

There's nothing saying that you can't define your own next() or prev() function. Its rather easy to do after getting around an annoyance of forward references.

class Demo {
    enum DayOfWeek {
        U, M, T, W, R, F, S;

        private DayOfWeek n;
        private DayOfWeek p;

        static {
            U.n = M; U.p = S;
            M.n = T; M.p = U;
            T.n = W; T.p = M;
            W.n = R; W.p = T;
            R.n = F; R.p = W;
            F.n = S; F.p = R;
            S.n = U; S.p = F;
        }

        public DayOfWeek next() { return this.n; }
        public DayOfWeek prev() { return this.p; }

    }

    public static void main (String[] args) {
        System.out.println(DayOfWeek.M.next());
        System.out.println(DayOfWeek.U.prev());
    }
}
T
S

So...

  1. The enum was borrowed from the C tradition of an enum, not the Pascal tradition of ordinal types
  2. They didn't want to confuse enum with Enumeration
  3. You have the ability to get all the values back easily with an iterable type
  4. You can define a next() method that works any way you want it to.
10
  • 1
    I was thinking if the user just wants to have next() to know which enum comes after a given enum, having to iterate through the whole array looks somewhat undesirable from the algorithmic perspective, but I think it's doesn't really matter with enum (which guarantees to not consist of a lot of elements). A single memory addressing would fetch all of them anyway. Am I right?
    – InformedA
    Jul 9, 2014 at 5:22
  • Great answer, but the issue is really not about iteration. There is a big difference between iteration and, given a particular value, getting the next one. I would even suggest that these two concepts are completely orthogonal, i.e. they have nothing to do with each other. Maybe I am confused about the terminology, but, the way I see it, iteration is just processing all elements one after another; the order in which this happens is accidental, all that matters is that all elements will be processed exactly once. On the other hand, next() is all about order, which even might be cyclic.
    – proskor
    Jul 9, 2014 at 9:31
  • 1
    @proskor Remember that Java draws from the C tradition rather than the Pascal one... but its not that hard to make your own cyclical next function. Putting that functionality in for all enums would likely be a mistake.
    – user40980
    Jul 9, 2014 at 15:07
  • @proskor 'the way I see it, iteration is just processing all elements one after another', so you gave them an order after all, accidentally or not it doesn't really matter.
    – Dtex
    Jul 10, 2014 at 9:59
  • @Dtex Sure, the order in which the elements are processed during iteration doesn't matter; however the order defined by the next operation does matter. So, what is your point?
    – proskor
    Jul 10, 2014 at 11:36
3

It is because of the nature of enums (enum in Java), (enum in C#). They are just fixed constants in the language, holding essential data (sometimes just their own names or just identity), not a kind of list. Therefore if you need this kind of logic (which might be applicable to many cases), then you actually have to create the logic.

Apart of being some sort of linked list, it can be singleton too (see: Implementation Example: Using enum). It is more matter of use. Sadly enums (at least in Java) in this way tricker since you can't extend them or define an interface directly for them.

It is an open debate if it is good practice or not to use enums for some sort of constant list or singleton, the fact is, you can. I would vote against using it unless it is widely used pattern in the project. Smells like hacking for me if it is used locally.

2
  • But what if you really need a next() on enum. Say you want to know that August is an enum after July by calling July.next(). Then wouldn't you have to 'hack'?
    – InformedA
    Jul 9, 2014 at 5:16
  • Yes it is kind of hacking. I would recommend using APIs for these things, I regularly use JodaTime, they have such features, so you don't need to reinvent the wheel. Jul 9, 2014 at 5:39
2

enums are replaced with their constant values in the executable. they can not be traversed at runtime.

in C enum are part of the source code and the compiler replaces the enum with the constant int.

     // C source - enum gets replaced with constant
enum _tenum { A, B, C};
_tenum ft;
ft = B;
     // assembler enum is gone. only constant value 1 remains
mov DWORD PTR _ft$[ebp], 1

if (ft == B) {

cmp DWORD PTR _ft$[ebp], 1
jne SHORT $LN1@main

in Java enum are also part of the source file and the byte code generator replaces the enum with the public final static value.

Here is an explaination http://boyns.blogspot.com/2008/03/java-15-explained-enum.html

1
1

Technically speaking, there is a way to perform a next operation in both languages, though it varies between Java and C#.

C#

In C#, enumerations are number types at their core. You can simply perform addition with integers:

var day = DayOfWeek.Sunday;
foreach(var n in Enumerable.Range(0, 7))
    Console.WriteLine("Day of week: {0}", day + n);

note: the above works the same way with day++

Output:

Day of week: Sunday
Day of week: Monday
Day of week: Tuesday
Day of week: Wednesday
Day of week: Thursday
Day of week: Friday
Day of week: Saturday

Java

Java allows you to define enums as full-blown object types. As a result, you cannot simply increment it. However, StackOverflow shows several alternatives.

TL;DR: there's a somewhat hackish way of incrementing an enum, but the suggested way is to implement a next() function in the enum.

0

@dan-lyons answer for C# is okay, but it only works when:

  • the enum is defined using consecutive integer values
  • you know how many values there are
  • you know what their integer equivalents are.

Instead, I would suggest using Enum.GetValues() and iterating the collection it returns.

enum MyEnum
{
    Value1 = -4,
    Value2 = 0,
    Value3,       // = 1
    Value4,       // = 2
    Value5 = 100,
}

...

// We need to use Cast<>() because GetValues() only returns
// a non-generic Array, which can hold any type of object.
var values = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>();
foreach(var value in values)
{
    Console.WriteLine($"{value} = {(int)value}");
}

This will print out all explicitly defined values by their coded name and their integer equivalents.

Value1 = -4
Value2 = 0
Value3 = 1
Value4 = 2
Value5 = 100

You don't need to know the values or how many there are.

1
  • Not sure if it is equivalent but you can write ˋforeach (MyEnum value in values)ˋ which is more readable.
    – Phil1970
    May 26, 2017 at 16:20
0

Providing this kind of behavior on enums would only facilitate a hack.

Enums are not arrays. They may technically be implemented as arrays but their logical meaning is a limited number of grouped constants that may be used in a type-safe manner. There is no logical sequental relation between group members.

An enum type definition is not a list, it is not even a collection, so individual members do not have an index, the order they appear in your source code is logically meaningless.

With their DayOfWeek implementation, Microsoft is being pragmatic and causing confusion as to what an enum is and should be used for:

If cast to an integer, its value ranges from zero (which indicates DayOfWeek.Sunday) to six (which indicates DayOfWeek.Saturday)

How convenient... and wrong. The proper way would have been to offer a Week class with a static method:

static DayOfWeek Day(DayOfWeek pivot, int offset)

Then there would not be a roll-over issue and one would not have to abuse the enum.

-1

Before Java there was C, C++ and Pascal. Enumerations in C and C++ could have wildly different values - they did not need to be contiguous integers. This had the advantage that you could define an enum for things like Windows message codes, which were a sparse set of non-contiguous integers.

(Borland) Pascal took the other approach, where all enumerations had contiguous ordinal values starting from zero. This meant set arithmetic was easy (e.g. Define Jan..Dec as an enum, then SummerMonths as a set of months (July, Aug, September). It was then legal to write if (month in SummerMonths)... It was also memory efficient, since enums could be bit-mapped.

For better or worse, Java went down the C/C++ route. For that reason, a next() operation does not make good sense.

1
  • C# went the C route, but enums in Java are very different from that: they're not integer-based at all.
    – svick
    Jul 13, 2014 at 14:17
-5

Speaking for Java, what you are actually looking for is Enumeration (which is more like iterator) which has the nextElement support.

enum is a data type which allows variable to have a set of predefined values.

6
  • 7
    No, I think he really is talking about enum, not Enumeration. He mentioned days of the week. Such a thing is commonly handled using enums.
    – Neil
    Jul 8, 2014 at 9:27
  • I think the definition says it all. If enum is a data type, it can take one of the defined values. There is no concept of next element in that. Enumeration on the other cases are basically iterators over a collection of values where next makes sense. For a single value enum, next does not make sense Jul 8, 2014 at 9:33
  • Datatypes without operations are useless. next is just one of the many operations which make up a datatype, like equals or hashCode. Whether it makes sense or not depends on what you want to do with the datatype.
    – proskor
    Jul 8, 2014 at 9:47
  • Sorry proskor I did not understand your point. Primitive data types never had any operations. Jul 8, 2014 at 10:00
  • All data types have operations, including primitive ones. Integers can be added, multiplied etc. Booleans can be or-ed, and-ed etc. The most important of all - the check for equality - is also an operation. What you mean, is that primitive data types do not have methods (like classes do, for exmaple), which are just means to implement operations in a specific programming language. But that is not a general rule. There might be languages in which primitive data types could have methods too.
    – proskor
    Jul 8, 2014 at 10:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.