Возврат нового объекта наряду с другим значением

Это классическая проблема, с которой сталкивается каждый разработчик C #.

Позвольте мне разбить ваш вопрос на 2 вопроса. Первый,

Можно ли поймать несколько исключений одновременно?

Короче говоря, нет.

Что приводит к следующему вопросу,

Как мне избежать написания дублирующего кода, если я не могу перехватить несколько типов исключений в одном блоке catch ()?

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

  1. Инициализировать WebId в качестве запасного значения.
  2. Создайте новый Guid во временной переменной.
  3. Установите для WebId полностью созданную временную переменную. Сделайте это последним утверждением блока try {}.

Таким образом, код выглядит следующим образом:

try
{
    WebId = Guid.Empty;
    Guid newGuid = new Guid(queryString["web"]);
    // More initialization code goes here like 
    // newGuid.x = y;
    WebId = newGuid;
}
catch (FormatException) {}
catch (OverflowException) {}

Если выбрасывается какое-либо исключение, то WebId никогда не устанавливается на половину построенного значения и остается Guid.Empty.

Если построение запасного значения стоит дорого, а сброс значения намного дешевле, я бы переместил код сброса в его собственную функцию:

try
{
    WebId = new Guid(queryString["web"]);
    // More initialization code goes here.
}
catch (FormatException) {
    Reset(WebId);
}
catch (OverflowException) {
    Reset(WebId);
}
5
задан amit 22 June 2009 в 17:41
поделиться

5 ответов

Просто создайте новый класс и верните этот класс

class Result
{
   A* a;
   int i;
public:
   Result( A*a, int i ) : a(a), i(i) {
   }
   ~Result() { 
      delete a; 
   }
   // access functions, copy constructor, ...
};

Result getA() {
   //...    
   return Result(new A, intValue);  
}
2
ответ дан 13 December 2019 в 05:41
поделиться

Есть два основных способа решить эту проблему:

  1. Выполните очистку самостоятельно, с помощью try / catch.
  2. Используйте какое-то автоматическое управление памятью, например shared_ptr .

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

5
ответ дан 13 December 2019 в 05:41
поделиться

A shared_ptr был бы идеальным в этой ситуации, но если вы действительно не хотите их использовать, вы можете вернуть auto_ptr паре вместо этого содержащий объект и int.

3
ответ дан 13 December 2019 в 05:41
поделиться

Почему не через два эталонных параметра?

class AGetter
{
    // ..
    void get(std::auto_ptr<A>& a, int& i)
    {
         a = a_.release();
         i = i_;
    }
    // ..
};
1
ответ дан 13 December 2019 в 05:41
поделиться

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

int i;
std::auto_ptr<A> a = getA(&i);
1
ответ дан 13 December 2019 в 05:41
поделиться
Другие вопросы по тегам:

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