# Loops for enumerated types

I'm currently reading Code Complete by Steve McConnell. In section 12.6, Enumerated Types, he says that we can define first and last entries like limits:

Define the first and last entries of an enumeration for use as loop limits Defining the first and last elements in an enumeration to be Color_First, Color_Last, Country_First, Country_Last, and so on allows you to write a loop that loops through the elements of an enumeration. You set up the enumerated type by using explicit values, as shown here:

Visual Basic Example of Setting First and Last Values in an Enumerated Type

``````Public Enum Country
Country_First = 0
Country_China = 0
Country_England = 1
Country_France = 2
Country_Germany = 3
Country_India = 4
Country_Japan = 5
Country_Usa = 6
Country_Last = 6
End Enum
``````

Now the Country_First and Country_Last values can be used as loop limits:

Good Visual Basic Example of Looping Through Elements in an Enumeration

``````' compute currency conversions from US currency to target currency
Dim usaCurrencyConversionRate( Country_Last ) As Single
Dim iCountry As Country
For iCountry = Country_First To Country_Last
usaCurrencyConversionRate( iCountry ) = ConversionRate( Country_Usa, iCountry )
Next
``````

Why do we need duplicated indices on the edges for enumerated type?

• I'd imagine a nearby paragraph explains just that, but probably because iterating from first to last is more intent revealing than iterating from China to the USA. Nov 30, 2021 at 8:14
• Indeed finding a PDF it explicitly tells you that this "... allows you to write a loop that loops through the elements of an enumeration... [these] values can be used as loop limits" with the VB example `For iCountry = Country_First To Country_Last`. Nov 30, 2021 at 10:22
• Ok, nice. Why indices should be duplicated? Nov 30, 2021 at 10:23
• @EugZ "Why indices" Tangentially: that integer value is not an index. They do not have to be continuous, nor do they have to be 0- or 1-indexed. You can set these values to mimic those of an index, but that's just your choice to do so then. Nov 30, 2021 at 10:32
• @jonrsharpe: Haven't read it so I can't comment on the reasoning, but I personally dislike the notion that you should rely on continuity here. The integer values of the enum should not be of concern to the enum's consumer, and could be completely arbitrary for all the consumer cares. The posted answer is the correct one, but I seriously dislike the allround approach there. Unless VB does not have another way to enumerate its enum values - at which point I'd still call it a dirty workaround but at least one in absence of a good way of doing things. Nov 30, 2021 at 10:40

Let's say for some reason you want to iterate over all countries. "That's easy", you say:

``````for (i = Country_China; i <= Country_Usa; i++) {
// Do stuff
}
``````

and you write that loop construct at lots of places in your code.

The next day, your product owner comes along and says "Hey EugZ, we're launching in Albania soon, can you make sure the product supports that?". "Sure", you say, and think about adding `Country_Albania` to your enum. Where do you add `Country_Albania`?

1. Before `Country_China`, in order to maintain the alphabetical ordering? You now need to go and rewrite every instance of your loop construct to start at `Country_Albania` rather than `Country_China` - and you may well miss one.
2. After `Country_Usa`, in order to maintain the existing values of the enum? Same problem.
3. You could put `Country_Albania` in the middle of the list of countries. While this wouldn't break the loop construct, you've implicitly and undocumentedly made `Country_China` and `Country_Usa` magic values in the enum which must always be first and last, and all sorts of things will break if anyone ever changes them. Not good.

Adding explicit values for `Country_First` and `Country_Last` avoids a lot of these and similar issues; given the small amount of work needed to do it, it's almost a no-brainer.

• I'm not sure what language this is in, it seems strange not to have some way to get all possible values from an enum type.
– bdsl
Nov 30, 2021 at 13:50
• @bdsl Certainly neither C nor C# (`[Flags]`) let you do that. Nov 30, 2021 at 14:28
• @PhilipKendall C# absolutely lets you do that, for both name and values Nov 30, 2021 at 19:42
• "Adding explicit values for Country_First and Country_Last avoids a lot of these and similar issue" - It adds one extra point of failure, however - if you slap Country_Albania after Country_Last, your code won't work as it should. Adding something to the list of countries will never be just adding it to it and calling it a day - you have to remember to change Country_Last, too. Which is not a usual thing... Nov 30, 2021 at 20:03
• @T.Sar That does not give you all the legal values of a `[Flags]` enum. Nov 30, 2021 at 21:03