2009-05-07 4 views
1

Допустим, есть функция, которая возвращает перечисление:Значение для возврата для обозначения недопустимое значение

public enum ServerStatus 
{ 
    Down, 
    Up 
} 

private ServerStatus GetServerStatus(int time) 
{ 
    if (time >= 0 && time < 12) 
    { 
     return ServerStatus.Down; 
    } 
    else if (time >= 12 && time <= 23) 
    { 
     return ServerStatus.Up; 
    } 
    else 
    { 
     return ?? // Server status is neither Up nor Down 
    } 
} 

Должен ли я:

  1. Добавить "Ни" в ServerStatus
  2. Заставляет GetServerStatus вернуть ServerStatus? и вернуть Null
  3. возвращающие другой BOOL, которые указывают, если значение имеет смысл
+1

Как и в сторону, я бы, вероятно, переименовать «время» в «час», «hourOfDay», или что-то –

+0

я согласен. Но это поддельный, игрушечный пример, который я продумал, чтобы проиллюстрировать мою мысль. –

ответ

13

Если это дело не должно происходить на практике, и вы не ожидаете, чтобы произвести что-то другое, чем «Up» и ' Down ', тогда вы должны выбросить исключение.

+2

ArgumentOutOfRangeException, возможно; +1 –

+0

Условие никогда не должно происходить: если возникает исключение, мне все равно придется возвращать действительное значение, нет? –

+1

Нет; нет никакого возвращаемого значения, если вы выбрали исключение. –

2

Если вы не хотите генерировать исключение, вы всегда можете иметь неизвестное значение перечисления. Например, статус сервера может быть Up, Down или Unknown. Неизвестный статус может быть действительным в некоторых случаях (например, если вы не можете получить соединение с сервером). Это неизвестное значение может быть проверено как логическое значение, чтобы решить, является ли ответ значимым, если это необходимо.

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

2
private ServerStatus GetSeverStatus(int time) 
{ 
    if (time >= 0 && time < 12) 
    { 
     return ServerStatus.Down; 
    } 

    if (time >= 12 && time <= 23) 
    { 
     return ServerStatus.Up; 
    } 

    throw new ArgumentOutOfRangeException(); 
} 
0

Мое мышление было бы вдоль этих линий:

Если это исключительный случай (1 в 10000 звонков, один раз в год?) Или неисправимая ошибка, то возбудит исключение.

Если «неизвестный» случай не является исключительным или это восстанавливаемая ошибка, я бы пошел с «неизвестным» значением. Тогда возникает вопрос: добавляете ли вы третье значение или используете тип с нулевым значением?

Если это вполне вероятно, добавьте третье состояние «неизвестно» или «недостижимое».

Если это не так, то перейдите к типу с нулевым значением.

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

1

Это пример «как обеспечить выполнение моих предварительных условий». У вас есть несколько способов сделать это.

Один из способов, которым я действительно ценю, - это очень простая функция «запрограммирована контрактом», которая обрабатывает чистую бизнес-логику: утвердите правильное предварительное условие. Постройте над ним «безопасную» функцию, которая обеспечивает ввод : действителен.

// with a 'validity' return type 
public Pair<bool,ServerStatus> checkedGetServerStatus(uint time) { 
    Pair<bool,ServerStatus> p; 
    p.first = false; 
    if(time > 23) return p; 

    p.first = true; 
    p.second = GetServerStatus((int)time); 
    return p; 
} 

// or with an exception 
public ServerStatus GetServerStatusEx(uint time) { 
    if(time > 23) throw InvalidArgumentException(time); 

    return GetServerStatus((int)time); 
} 

Другим, может быть, лучшим, было бы изменение типа аргумента функции во что-то, что не может быть ошибкой.

class ServerTime { 
    public ServerTime(uint hours) { seconds = (hours%24)*3600; } 
    private uint seconds; 
} 

public ServerStatus GetServerStatus(ServerTime time) { 
... 
} 
Смежные вопросы