问题
I've recently found myself needing (yes, needing) to define absurdly long switch
statements and enum
declarations in C# code, but I'm wondering what people feel is the best way to split them into logical subsections. In my situation, both the enum values and the cases (which are based on the enum values) have fairly clear groupings, yet I am slightly unsure how to reflect this in code.
Note that in my code, I have roughly 5 groups of between 10 and 30 enum values/cases each.
The three vaguely sensible options I can envisage are:
- Define
#region
blocks around all logical groups of cases/enum values within the declaration (optionally separated by blank lines). - Comment each group with it's name, with a blank line before each group name comment.
- Do nothing whatsoever - simply leave the switch/enum as a huge list of cases/values.
Which do you prefer? Would you treat enums and switches separately? (This would seem slightly odd to me.) Now, I wouldn't say that there is any right/wrong answer to this question, though I would nonetheless be quite interested in hearing what the general consenus of views is.
Note 1: This situation where I might potentially have an extremely long enum declaration of 50/100+ values is unfortunately unavoidable (and similarly with the switch), since I am attempting to write a lexer (tokeniser), and this would thus seem the most reasonable approach for several reasons.
Note 2: I am fully aware that several duplicate questions already exist on the question of whether to use regions in general code (for structuring classes, mainly), but I feel my question here is much more specific and hasn't yet been addressed.
回答1:
Sure, region those things up. They probably don't change much, and when they do, you can expand the region, make your changes, collapse it, and move on to the rest of the file.
They are there for a reason, use them to your advantage.
回答2:
You could also have a Dictionary<[your_enum_type], Action> (or Func instead of Action) or something like that (considering your functions have a similar signature). Then you could instead of using a switch, instead of:
switch (item)
{
case Enum1: func1(par1, par2)
break;
case Enum2: func2(par1, par2)
break;
}
you could have something like:
public class MyClass
{
Dictionary<int, Action<int, int>> myDictionary;
//These could have only static methods also
Group1Object myObject1;
Group2Object myObject2;
public MyClass()
{
//Again, you wouldn't have to initialize if the functions in them were static
myObject1 = new Group1Object();
myObject2 = new Group2Object();
BuildMyDictionary();
}
private Dictionary<int, Action<int, int>> BuildMyDictionary()
{
InsertGroup1Functions();
InsertGroup2Functions();
//...
}
private void InsertGroup2Functions()
{
myDictionary.Add(1, group2.AnAction2);
myDictionary.Add(2, group2.AnotherAction2);
}
private void InsertGroup1Functions()
{
myDictionary.Add(3, group1.AnAction1);
myDictionary.Add(4, group1.AnotherAction1);
}
public void DoStuff()
{
int t = 3; //Get it from wherever
//instead of switch
myDictionary[t](arg1, arg2);
}
}
回答3:
I would leave it as a huge list of cases/ values.
回答4:
If there are some cases that have the same code block, using the Strategy design pattern, could remove the switch block. This can create a lot of classes to you, but will show how complex it really is, and split the logic in smaller classes.
回答5:
Get rid of the enums and make them into objects. You could then call methods on your objects and keep the code separated, maintainable, and not a nightmare.
There are very few cases when you would actually need to use an enum instead of an object and nobody likes long switch statements.
回答6:
Here's a good shortcut for people who use regions.
I was switching between Eclipse and Visual Studio when I tried to go full screen in VS by pressing
Ctrl-M-M
and lo and behold, the region closed and expanded!
来源:https://stackoverflow.com/questions/1050638/would-you-use-regions-within-long-switch-enum-declarations