12

Possible Duplicate:
How to enumerate an enum?

Suppose that i have an enumeration like that:

public enum Cars
{
    Audi = 0,
    BMW,
    Opel,
    Renault,
    Fiat,
    Citroen,
    AlfaRomeo,
}

Do i have a chance to iterate between Opel and Citroen? I want to give these values as parameters of a method.

Community
  • 1
  • 1
sanchop22
  • 2,729
  • 12
  • 43
  • 66
  • `var cars = Enum.GetValues(typeof (Cars)).Cast().Where(i => i>=(int)Cars.Opel && i<=(int)Cars.Citroen).Cast();` – Jonas Elfström May 08 '12 at 13:29
  • Avoid using enums for this kind of enumerations. It introduces a maintenance nightmare if somebody inserts a value, for instance. And it seems rather plausible that your software will support other cars eventually. – Jacek Gorgoń May 08 '12 at 13:35

3 Answers3

13

This will work:

for(Cars car=Cars.Opel; car<=Cars.Citroen; car++)
{
  Console.WriteLine(car);
}

but you have to make sure that the start value is less than the end value.

EDIT
If you don't hardcode the start and end, but supply them as parameters, you need to use them in the correct order. If you just switch "Opel" and "Citroen", you will get no output.

Also (as remarked in the comments) the underlying integer values must not contain gaps or overlaps. Luckily if you do not specify values yourself (even the '=0' is not needed), this will be the default behaviour. See MSDN:

When you do not specify values for the elements in the enumerator list, the values are automatically incremented by 1.

Hans Kesting
  • 38,117
  • 9
  • 79
  • 111
  • 1
    @NikhilAgrawal Yes it will. An enum value is an integer (by default) under the hood. I tested it (in LinqPad) and it worked fine. – Hans Kesting May 08 '12 at 13:19
  • 4
    This relies on your knowing the minimum and maximum of the `Enum`, and it also assumes that the enums form a contiguous range of integers. Downvote from me. It doesn't work if the range is not contiguous (think `enum Foo { A = 1, B = 17 }`). – jason May 08 '12 at 13:23
  • @Jason - thanks for the explanation of the downvote (I was wondering). I know it depends on the ordering etc, that's the reason for that "start less than end" remark. – Hans Kesting May 08 '12 at 13:25
  • @Hans Kesting: It's not just the ordering. It's also that you're assuming the values form a contiguous sequence; they need not and this loops doesn't produce the correct values if they don't. – jason May 08 '12 at 13:26
  • If the enum defined the integer for each value then you could know this would work, but as is you're relying on undefined behaviors for the implementation of the enum. -1. – Servy May 08 '12 at 13:30
  • 1
    @Servy - if you don't define values for the enum-values, then by default they start at zero for the first defined value, and are "one more" for following values. See http://msdn.microsoft.com/en-us/library/cc138362.aspx, it *is* defined behaviour. – Hans Kesting May 08 '12 at 13:41
  • I don't understand the downvotes, if you want to iterate between Opel and Citroen, it's because you know that the order won't change. It's not a very good practice to use enums for this, but Hans answers the question perfectly. – Meta-Knight May 08 '12 at 14:03
2

You can use the following code to loop trough an enum:

string[] names = Enum.GetNames(typeof(Cars));
Cars[] values = (MyEnum[])Enum.GetValues(typeof(Cars));

for( int i = 0; i < names.Length; i++ )
{
    print(names[i], values[i]);
}

If you know that you want to start at Opel and go to Citroen, you set the start and end values of i to the correct index in your array.

That would look something like this:

  string[] names = Enum.GetNames(typeof(Cars));
  Cars[] values = (Cars[])Enum.GetValues(typeof(Cars));

  int start = names.ToList().IndexOf("Opel");
  int end = names.ToList().IndexOf("Citroen") + 1;

  for (int i = start; i < end; i++)
  {
      Console.WriteLine(names[i] + ' ' + values[i]);
  }
Wouter de Kort
  • 39,090
  • 12
  • 84
  • 103
  • 1
    If the enum defined the integer for each value then you could know this would work, but as is you're relying on undefined behaviors for the implementation of the enum. -1. – Servy May 08 '12 at 13:31
  • @Servy The question states that the first value is zero and by default the values are consecutive. Off course, if you change the default behavior this won't work, but the poster isn't doing that. – Wouter de Kort May 08 '12 at 13:47
1

Also, using LINQ:

var values = (from e in Enum.GetValues(typeof(Cars)) as Cars[]
              where e >= Cars.Opel && e <= Cars.Citroen
              select e);
// the same as above, but using lambda expressions
// var values = (Enum.GetValues(typeof(Cars)) as Cars[]).Where(car => car >= Cars.Opel && car <= Cars.Citroen); 

foreach(Cars c in values) Console.WriteLine(c);
Romano Zumbé
  • 7,893
  • 4
  • 33
  • 55
moribvndvs
  • 42,191
  • 11
  • 135
  • 149
  • If the enum defined the integer for each value then you could know this would work, but as is you're relying on undefined behaviors for the implementation of the enum. -1. – Servy May 08 '12 at 13:32
  • IF the OP had asked for a generalized solution, I would agree with you. However, he did not, so I don't. – moribvndvs May 08 '12 at 13:52