Вопрос по .net, c#-4.0 – C # Обеспечение допустимых значений перечисления - метод будущего

7

Я пишу некоторый код с простым оператором switch на основе значений Enum. Мне пришло в голову, что в какой-то момент в будущем разработчик может добавить новое значение, поэтому я включил метод по умолчанию, чтобы захватить это во время выполнения и выдать исключение. Однако я осознал, что должен делать это каждый раз, когда прибегаю к такой логике, и что я вижу такие проблемы только во время выполнения, а не во время компиляции.
Мне интересно, есть ли какой-нибудь код, который я могу добавить, чтобы заставить компилятор сообщить разработчику, что ему нужно обновить определенные методы в случае, если они обновляют значения перечисления - помимо простого добавления комментариев к самому перечислению?

например (приведенный ниже пример чисто теоретический; я выбрал статусы из жизненного цикла разработки, чтобы убедиться, что это что-то знакомое большинству).

public enum DevelopmentStatusEnum
{
    Development
    //, QA //this may be added at some point in the future (or any other status could be)
    , SIT
    , UAT
    , Production
}

    public class Example
    {
        public void ExampleMethod(DevelopmentStatusEnum status)
        {
            switch (status)
            {
                case DevelopmentStatusEnum.Development: DoSomething(); break;
                case DevelopmentStatusEnum.SIT: DoSomething(); break;
                case DevelopmentStatusEnum.UAT: DoSomething(); break;
                case DevelopmentStatusEnum.Production: DoSomething(); break;
                default: throw new StupidProgrammerException(); //I'd like the compiler to ensure that this line never runs, even if a programmer edits the values available to the enum, alerting the program to add a new case statement for the new enum value
            }
        }
        public void DoSomething() { }
    }
    public class StupidProgrammerException: InvalidOperationException { }

Это немного академично, но я вижу в этом полезность для придания прочности своему приложению. Кто-нибудь пробовал это раньше / получил хорошие идеи о том, как этого можно достичь?

Заранее спасибо,

JB

Я делаю это так же, как вы. David Heffernan
Каждый раз, когда вы пишете оператор switch, вы должны рассмотреть возможность рефакторинга кода вместо использования полиморфизма.See this exerpt книги Мартина ФаулераRefactoring, Это заставит ваш код придерживаться принципа Open-Closed (OCP) и поможет следующему разработчику избежать пропущенного изменения инструкции switch где-либо. :-) Ulf Åkerstedt

Ваш Ответ

4   ответа
0

что вы можете написать правила для StyleCop и запустить их в событии PostBuild, и они могут выводить предупреждения в окне Build. Мы начали пытаться добавить предупреждение за игнорирование возвращаемого значения метода, но так и не дошли до его завершения. В последний раз, когда я изучал это, вам нужно было проанализировать ИЛ, что не всегда весело. Конечно, я думаю, это зависит от вашего определения веселья.

13

а класс с открытыми статическими полями только для чтения, которые являются экземплярами класса. Посмотрите, что .Net Framework делает с цветами, например. Существует класс Color, и вы можете использовать такие объекты, как Color.Black, Color.Blue и т. Д. Они не являются константами, но предлагают почти все те же преимущества. Кроме того, у них есть другие преимущества, которых нет у констант. См. Спецификацию языка C # версии 3, которая также немного говорит об этом.

Но идея в том, что у вас нет заявления по делу. Вы добавляете достаточно других свойств к каждому & quot; enum & quot; член, что метод (DoSomething или что-то еще) может обрабатывать его правильно. Когда другой разработчик хочет добавить другой объект-член, он должен предоставить необходимые атрибуты. Мой пример: мне нужно было "enum" для различных действий, которые пользователь может выполнять в системе. Эти действия нужно было проверять на предмет разрешений, регистрировать и т. Д. Мне также требовались родительские и дочерние действия (переименование чего-либо является «частью» его редактирования и т. Д.), Абстрактные действия, используемые для группировки действий для целей фильтрации, и специальные действия. & Quot; все & Quot; и "Нет" (Ни один не определен). Каждому из них нужен был идентификатор и текст в базе данных. Я хотел, чтобы это все еще работало, если кто-то изобрел новый тип действия. Я сделал что-то вроде этого (много кода опущено, чтобы дать вам идею):

  public class Action
  {
    protected Action(bool Abstract, Action Parent, int ID, string Name, bool Undefined)
    { /* snip */ }
    protected Action(bool Abstract, Action Parent, int ID, string Name)
      : this(Abstract, Parent, ID, Name, false)
    { }
    //----------------------------------------------------------------------------------------
    public static readonly Action All = new Action(true, null, 0, "All");
    public static readonly Action None = new Action(false, All, 6, "(Undefined)", true);
    public static readonly Action Modifying = new Action(true, All, 1, "Modifying");
    public static readonly Action Creating = new Action(false, Modifying, 2, "Creating");
    public static readonly Action Deleting = new Action(false, Modifying, 3, "Deleting");
    public static readonly Action Editing = new Action(false, Modifying, 4, "Editing");
    public static readonly Action Exporting = new Action(false, All, 5, "Exporting");
    public static readonly Action Renaming = new Action(false, Editing, 7, "Renaming");
    /* snip */
    //----------------------------------------------------------------------------------------
    /* template for new entries:
    public static readonly Action  = new Action(false, All, , "");
    */
  }

Есть больше действий. И есть ряд методов в других классах, которые работают с действиями. Все они продолжают работать, пока каждое действие предоставляет необходимую информацию. Разработчик, добавляющий действие, обязан предоставить информацию. Если текущих атрибутов недостаточно для какого-либо будущего, «специального» действие, то больше атрибутов нужно будет добавить позже. Обратите внимание, что конструкторы защищены, поэтому только сам класс может создавать действия. Я опустил много кода в главном конструкторе, который проверяет дубликаты идентификаторов и имен и многое другое. Теперь вы можете использовать его так:

Log.LogAction(Action.Renaming);

Метод LogAction не содержит оператора case. Он использует атрибуты действия.

Каково ваше перечисление?

С уважением

Error: User Rate Limit Exceeded JohnLBevan
Error: User Rate Limit Exceededmsdn.microsoft.com/fr-fr/library/vstudio/…
Error: User Rate Limit Exceededdeveloper42.wordpress.com/2012/10/12/path-finder-in-c JohnLBevan
3

сырой, может быть, его можно улучшить с помощью лучшего дизайна:

bool allCasesHandled;

switch (myEnumValue)
{
    case MyEnum.Value1:
        allCasesHandled = true;
        break;

    //default:
    //  allCasesHandled = true;
    //  break;
}
System.Diagnostics.Debug.WriteLine(allCasesHandled);

Если вы попытаетесь скомпилировать это, вы получите ошибку «использование неназначенной переменной».

Это немного громоздко в обслуживании, но для простых случаев это может быть полезно, особенно с комментарием к строке, которая предназначена для сбоя.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded JohnLBevan
2

я ошибаюсь, но я не думаю, что компилятор предлагает такие предупреждения. Вы можете обнаружить такие проблемы с некоторыми модульными тестами, которые вызывают метод, подобный приведенному выше, со всеми возможными значениями перечисления (используйтеEnum.GetValues () за это). Каждый раз, когда разработчик добавляет элемент enum и забывает изменить все операторы switch, по крайней мере, один модульный тест завершится неудачей с & quot; StupidProgrammerException & quot; (кстати: я бы бросил ArgumentOutOfRangeException).

Error: User Rate Limit ExceededInvalidEnumArgumentExceptionError: User Rate Limit Exceeded

Похожие вопросы