Define enums within a method in C#?
I have mainly a C++ background and I am learning C#. So, I need some help with C# idioms and styl开发者_运维知识库e.
I am trying to write, in C#, a small text-file parsing method in which I need a simple state variable with three states. In C++ I would declare an enum
like this for the state variable:
enum { stHeader, stBody, stFooter} state = stBody;
...and then use it in my parsing loop like this:
if (state == stHeader && input == ".endheader")
{
state = stBody;
}
In C# I realize that it is not possible to declare an enum
inside a method. So, what I am supposed to do for sake of clean style? Declare this internal enum
outside of the method? Use magic numbers 1,2,3? Create a separate class for this?
Please help me clear up my confusion.
The closest you can get is a private nested enum with in the class:
public class TheClass
{
private enum TheEnum
{
stHeader,
stBody,
stFooter
}
// ...the rest of the methods properties etc...
}
You can also use the constant variables but I prefer and I think is better code style to use Enums
public class Class1
{
private enum TheEnum
{
stHeader,
stBody,
stFooter
}
public void SomeMethodEnum()
{
TheEnum state = TheEnum.stBody;
switch (state)
{
case TheEnum.stHeader:
//do something
break;
case TheEnum.stBody:
break;
case TheEnum.stFooter:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
public void SomeMethodConst()
{
int state = 1;
const int Header = 1;
const int Body = 2;
const int Footer = 3;
switch (state)
{
case Header:
break;
case Body:
break;
case Footer:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
I would also favour the Enum approach. Plus, although that is not the case here, it has advantages over the CONSTS when you want to combine them as flags, since you have a method to easily test for that.
You can't declare an enum
in method scope (recapping Willem van Rumpt's answer above) but instead you can declare an inner private class to do the state-tracking and reuse it in your class methods. The containing class or its clients need not know about that auxiliary class.
class Program
{
private class Parser
{
public string pname = "ParserPam";
public enum pstate { rewind=-1, stdHeader, stBody, stFooter }
public pstate state = pstate.stdHeader;
//Implement state transition logic as methods
public void tick() => this.state = pstate.stBody;
public void tock() => this.state = pstate.stFooter;
public void rewind() => this.state = this.state - 1;
public override string ToString()
{
return $"{this.pname} state: {this.state}";
}
}
static void ParseFile(string filename)
{
Parser fp = new Parser(); //This object tracks your method's state
Console.WriteLine(fp); // "ParserPam state: stdHeader"
if (fp.state == Parser.pstate.stdHeader)
{
fp.tick(); // Transition
// Do stuff
}
// Do more stuff
Console.WriteLine(fp); // "ParserPam state: stBody"
fp.tock();
Console.WriteLine(fp); // "ParserPam state: stFooter"
fp.rewind();
Console.WriteLine(fp); // "ParserPam state: stBody"
}
static void Main(string[] args)
{
ParseFile( @"C:\Example" ); // Client call
}
}
In this case, Parser
is your private inner class whose instances can track state -- it is not visible outside of Program
. ParseFile
is a method that utilizes Parser
.
Output
ParserPam state: stdHeader
ParserPam state: stdBody
ParserPam state: stFooter
ParserPam state: stBody
I know this is old, so this is mainly for folks looking for ideas.
The closest I can think of to creating an 'enum' type, clean structure as required, within a method is to use a dictionary.
var stateOpt = new Dictionary<string, byte>() { { "stHeader", 0 }, { "stBody", 1 }, { "stFooter", 2 } };
var state = stateOpt["stBody"];
You can then do what you need in your condition...
if (state == stateOpt["stHeader"] && input == ".endheader")
{
state = stateOpt["stBody"];
}
精彩评论