Определить перечисления внутри метода в C #? - PullRequest
24 голосов
/ 09 апреля 2011

У меня в основном фон C ++, и я изучаю C #. Итак, мне нужна помощь с идиомами и стилем C #.

Я пытаюсь написать в C # небольшой метод анализа текстового файла, в котором мне нужна простая переменная состояния с тремя состояниями. В C ++ я бы объявил enum вот так для переменной состояния:

enum { stHeader, stBody, stFooter} state = stBody;

... а затем используйте его в моем цикле синтаксического анализа следующим образом:

if (state == stHeader && input == ".endheader")
{
  state = stBody;
}

В C # я понимаю, что невозможно объявить enum внутри метода. Итак, что я должен делать ради чистого стиля? Объявить этот внутренний enum вне метода? Использовать магические числа 1,2,3? Создать отдельный класс для этого?

Пожалуйста, помогите мне прояснить мою путаницу.

Ответы [ 4 ]

29 голосов
/ 09 апреля 2011

Самое близкое, что вы можете получить - это личное вложенное перечисление в классе:

public class TheClass
{
    private enum TheEnum 
    {
       stHeader, 
       stBody, 
       stFooter
    }

    // ...the rest of the methods properties etc... 
}
7 голосов
/ 09 апреля 2011

Вы также можете использовать постоянные переменные, но я предпочитаю, и я думаю, что лучше использовать стиль кода для использования 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();
        }

    }
}
0 голосов
/ 13 сентября 2018

Вы не можете объявить enum в области действия метода (повторяя ответ Виллема ван Румпта выше), но вместо этого вы можете объявить внутренний закрытый класс для отслеживания состояния и повторно использовать его в своем классе методы. Содержащий класс или его клиенты не должны знать об этом вспомогательном классе.

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
    }
}

В этом случае Parser - это ваш закрытый внутренний класс, экземпляры которого могут отслеживать состояние - он не виден за пределами Program. ParseFile - это метод, который использует Parser.

выход

ParserPam state: stdHeader
ParserPam state: stdBody
ParserPam state: stFooter
ParserPam state: stBody
0 голосов
/ 01 августа 2017

Я также предпочел бы подход Enum. Кроме того, хотя в данном случае это не так, у него есть преимущества перед CONSTS, когда вы хотите объединить их как флаги, поскольку у вас есть метод, позволяющий легко проверить это.

...