2012-02-23 4 views
1

У меня есть класс с закрытым полем Dictionary<string, T> (users), где ключ string представляет собой имя пользователя. Я написал несколько методов для этого класса, например, метод GetValue(string userid) возвращает объект T, который связан с указанным именем пользователя.Обработка исключений в пользовательском классе

Я бы справился с исключениями, которые могут возникать в этом классе и которые вызваны Словарем. Например:

  • , если указанный ключ является пустым, Dictionary бросает ArgumentNullException;
  • если указанный ключ не существует в Dictionary, он выбрасывает KeyNotFoundException.

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

public T GetValue(string userid) 
{ 
    try 
    { 
     return users[userid]; 
    } 
    catch(ArgumentNullException ex1) 
    { 
     // re-throw the same exception 
    } 
    catch(KeyNotFoundException ex2) 
    { 
     throw new UserIdNotFoundException("The specified userid does not exist.", ex2); // custom exception 
    } 
} 

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

public T GetValue(string userid) 
{ 
    if (userid != null) 
    { 
     if(users.ContainsKey(userid)) 
      return users[userid]; 
     else throw new UserIdNotFoundException("The specified userid does not exist.", ex2); // custom exception 
    } 
    else throw new ArgumentNullException(...); 
} 

Третий подход похож на второй, но он использует TryGetValue метод Dictionary.

public T GetValue(string userid) 
{ 
    if (userid != null) 
    { 
     T value; 
     if(users.TryGetValue(userid, out value)) 
      return value; 
     else throw new UserIdNotFoundException("The specified userid does not exist.", ex2); // custom exception 
    } 
    else throw new ArgumentNullException(...); 
} 

В чем преимущества и недостатки каждого из этих подходов? best practices for handling exceptions говорят, что:

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

в моем случае метод GetValue(string userid) будет вызываться редко, но потенциальные пользователи класса могут использовать его очень часто.

ответ

2

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

Помимо этого, ваш внутренний метод вызывает исключение, и вы знаете, что они означают, часто лучше всего обернуть их в свои собственные исключения, если вы не уверены, что все такие исключения всегда будут иметь одинаковое семантическое значение в любое время, когда они встречаются в коде ты звонишь. В противном случае предположим, что при попытке добавить дубликата пользователя Словарь выдает ArgumentException. Если вы позволите этому перколить как ArgumentException, а не обернуть его как что-то еще, а позже станет возможным код где-нибудь в вашем методе AddUser, чтобы выбросить ArgumentException для чего-то другого, вам может быть сложно помочь вашему абоненту различать ArgumentException, вызванный дублированным пользователем, по сравнению с ArgumentException, который возникает по другой причине.

2

ContainsKey и TryGetValue как способ избежать метания KeyNotFoundException

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

подход прост в использовании, чем подход ContainsKey, но только если вы хотите проверить ключ в коллекции, а также хотите получить связанное с ним значение. Если вы хотите только проверить, что ключ присутствует или не используется только ContainsKey.

Дополнительная информация: Dictionary Object (ContainsKey Vs. TryGetValue) может вам помочь.

2

Это зависит от предназначения вашего класса.Например, если ваш класс должен действовать как оболочка словаря, клиентам может быть полезно распространять подобное поведение ошибок/исключений типичного Dictionary. Если ваш класс реализует что-то более сложное (скорее всего), я бы сказал, что вам лучше представить свои собственные ошибки вызывающему. Что касается подхода, сделайте то же самое подтверждение ввода, которое вы бы сделали при нормальном взаимодействии Dictionary. Другими словами, если вы обычно проверяете ContainsKey или TryGetValue перед добавлением в Dictionary, продолжайте делать это здесь, но тогда нет необходимости бросать новое исключение. Вместо этого сообщайте об ошибке обратно вызывающему абоненту в терминах, которые они могут понять. Им не нужно знать, что вы используете Dictionary под капотом.

0

third Реализация является лучшей, поскольку она является самой быстрой и кратчайшей.

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

первый реализация является худшим:

  • Это не функционально эквивалентны в случае, если аргумент равен нулю.
  • Он получает штраф за исполнение от try заявление - компилятор должен будет установить некоторые данные в стеке, очевидно.
  • Существует также проблема стиля, на мой взгляд, с программами, в которых широко используются catch. Лучшее, что можно сделать с исключениями, - это часто позволять им пузыриться до тех пор, пока они не будут зарегистрированы или что-то можно сделать с ними.
Смежные вопросы