There is one essential flaw in other answers: some problems when your enumeration type has members with explicitly defined values, and if some values get identical values. Those identical values are sometimes used to provide synonyms. Besides, sometimes you need to exclude some auxiliary members for the traversal.
For a comprehensive solution with a number of extras please see my article Enumeration Types do not Enumerate! Working around .NET and Language Limitations. In other articles of my enumeration series referenced in this article, you can find some interesting applications of this approach.