Как проверить несколько условий или для оператора If для перечислений в C#?

#c# #linq #enums

Вопрос:

У меня есть класс перечисления с именем AccountStatus с почти 20 значениями перечисления. И мне нужно выполнить некоторую операцию, если совпадают 10 перечислений. и выполните другую операцию, если все перечисления совпадают. Теперь мой я написал код следующим образом

 public enum AccountStatus
{
Unknown ,
Pending,
Deleted,
Declined,
Deactivated,
Processing,
......
}
 

Мой образец, если условие

 if(status == AccountStatus.Unknown || status == AccountStatus.Pending || status == AccountStatus.Declined 
 ||status == AccountStatus.Hold|| status == AccountStatus.Stopped|| status == AccountStatus.Deferred
 ||status == AccountStatus.Rejected || status == AccountStatus.Waiting|| status == AccountStatus.Deleted)
{
   // Perform Some operation.
}
 

Есть ли лучший способ избежать этих многих или условий?

Комментарии:

1. Пожалуйста, включите определение AccountStatus . Если в тестируемых значениях нет пробелов (и они не приписываются [Flags] ), вы можете выполнить тест диапазона (или, возможно, пару тестов диапазона, если есть 1 пробел).

2. Согласовано с тестом диапазона, в противном случае, если это невозможно, вы можете использовать переключатель с выпадением первых 10 значений, а затем по умолчанию для остальных

Ответ №1:

Возможным решением было бы превратить проверку в операцию переключения:

 switch (status)
{
    case AccountStatus.Unknown:
    case AccountStatus.Pending:
    case AccountStatus.Declined:
    case AccountStatus.Hold:
    case AccountStatus.Stopped:
    case AccountStatus.Deferred:
    case AccountStatus.Rejected:
    case AccountStatus.Waiting:
    case AccountStatus.Deleted:
    {
       // Perform Some operation.
    }
    break;
}
 

Ответ №2:

Если ваши enum проверки всегда проверяют эти значения, вы можете расположить их в нужном вам порядке. Перечисление на самом деле-это просто int значение, и вы можете присваивать int им значения по своему усмотрению. Таким образом, вы также можете сравнить an enum с an int .`

 public enum AccountStatus {
  Unknown = 0,
  Pending = 1,
  Declined = 2
  // and so on
}
 

Значения, которые я там установил, совпадают со значениями по умолчанию, но вы можете увидеть, как вы можете использовать другие значения вместо значений по умолчанию.

Затем вы просто сравниваете, как обычно:

 
public static void Main() {
  AccountStatus s = AccountStatus.Pending;

  if (s <= AccountStatus.Pending) {
    // Perform some operation
  } else {
    // Perform some other operation
  }
}
 

Ответ №3:

Ответ Max Play с утверждением о большом переключателе хорош в своей простоте. Однако с ним невозможно работать, если у вас действительно много перечислений. Также очень сложно провести модульное тестирование, чтобы убедиться, что вы не забыли case

Если мне кажется, что если состояние учетной записи неизвестно / Ожидание / Отклонено / Ожидание / и т. Д. в этом статусе есть что-то общее. Эта общая вещь заставляет вас по-разному обрабатывать учетные записи с этими статусами: есть две «группы учетных записей».

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

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

 [Flage]
enum CarType
{
    None = 0x00,
    Gaz = 0x01,
    Electric = 0x02,
    FourWheelDrive = 0x04
    AirConditioning = 0x08,
    SunRoof = 0x10,
    CruiseControl = 0x20,
    ... // etc

    BMW1Series      = Gaz,
    BMW4Series      = Gaz | AirConditioning,
    BMW4x4          = Gaz | FourWheelDrive,
    BMW4x4Executive = Gaz | FourWheelDrive | AirConditioning | CruiseControl,

    TotoyataPrius    = Gaz | Electric | Airconditioning | CruiseControl,
    ...
 

Теперь, чтобы узнать, нуждается ли автомобиль в обслуживании кондиционера во время регулярного технического обслуживания, вы можете воспользоваться большим переключателем, в котором у вас есть все известные модели автомобилей:

 bool NeedsAirconditioningCheck(Car car)
{
   switch (car.CarType)
   {
       case ToyotaPrius:
       case BMW4x4Executive:
       ...
       // etc, do this for all 1254 car models that have an airconditioning
          return true;

       default:
           return false;
}
 

Используя флаги, это было бы намного проще:

 bool NeedsAirconditioningCheck(Car car)
{
    return (car.CarType amp; CarType.AirConditioning) == CarType.AirConditioning;
}
 

Другой пример: Автомобиль является гибридным, если он использует Газ и электричество:

 bool IsHybrid(Car car)
{
    CarType Hybrid = CarType.Gaz | Cartype.Electric;
    return (car.Cartype amp; Hybrid) == Hybrid;
}
 

Преимущества:

  • Эти процедуры не придется менять, если ваше перечисление будет дополнено новыми моделями автомобилей
  • Эти процедуры не придется менять, если мы придумаем новую функцию. Например, если изобретена новая функция, подобная KeepYourLane этой, то, по-видимому, у всех существующих моделей автомобилей этой функции не было. Все старые типы карт менять не придется, только недавно добавленные.
  • Намного проще для понимания и визуальной проверки правильности метода
  • Проще в модульном тестировании