Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Обработка исключений


Автор: Хоббит 25.6.2006, 12:59
Есть класс (допустим выполняющий операции с БД). Есть методы в них может произойти исключительная ситуация... допустим при выполнения sql команды .... надо его обработать на более высоком уровне чем этот метод, да и текст по культурней вывести ... то есть я думаю надо так

Код

public void Connect()
{
  try
  {
    действия с Sql которые могут породить исключение
  }
  catch
  {
     throw(параметры); //создание своего культурного исключения
  } 
}


в коде

try
{
  Connect();
}
catch
{
  Обработка уже моего исключения
}


Я правильно написал ... просто визуалки рядом нет... не могу проверить! 

Автор: B3cK 25.6.2006, 13:37
Код

public void Connect()    
{    
 ...
     throw new Exception(); //создание своего культурного исключения    
 ...    
}    


в коде    
try    
{    
  Connect();    
}    
catch(Exception e)    
{    
  Обработка уже моего исключения    
}
 

Автор: arilou 27.6.2006, 17:52
Хоббит, не так, а вот так:

Код

public void Connect()
{
  try
  {
    действия с Sql которые могут породить исключение
  }
  catch(Exception e)
  {
     throw new МоеИсключение(параметры, ex); //создание своего культурного исключения с передачей реального в InnerException.
  } 
}


в коде

try
{
  Connect();
}
catch(МоеИсключение e)
{
  Обработка уже моего исключения
}
 

Автор: Exception 28.6.2006, 00:21
Цитата(Хоббит @  25.6.2006,  13:59 Найти цитируемый пост)
  catch


Цитата(B3cK @  25.6.2006,  14:37 Найти цитируемый пост)
catch(Exception e)  


Отрывать руки и не приклеивать! Обязательно надо делать свитчи на разные типы исключений, иначе - совать его в InnerException. А то неизвестно - у тебя полетело исключение потому что SQL неправильный или потому что где-то что-то не кастуется.

Вот так:

Цитата(arilou @  27.6.2006,  18:52 Найти цитируемый пост)
 throw new МоеИсключение(параметры, ex);

 

Автор: mr.DUDA 28.6.2006, 00:24
З.Ы. могу только проконстатировать, что при постоянном использовании оператора trrow в своих приложениях, производительность серьёзно падает... Это действительно так. 

Автор: Exception 28.6.2006, 00:24
P.S. Лично мне нравится свитч из Немерле:

Код
в коде
try
{
  Connect();
}
catch
{
   | e : МоёИсключение => ...
   | e : ТвоёИсключение => ...
   | _ => Console.WriteLine("Что-то другое")
}
 

Автор: agl 2.11.2006, 17:59
Поделитесь пожалуйста мыслями, чем обработка исключений(при помощи встроенных классов исключений или написанных программистом) лучше чем обыкновенные проверки в if'ах.
Например есть класс Queue и в нем имеется функция get(). В функции надо обработать ситуацию когда пользователь пытается получить из пустой очереди какую то инфу.
1-ый вариант обработки возможной ошибки
Код

public class Queue{
//...........................................

      public char get()
        {
            if(this.getloc == this.putloc)
            {
                Console.WriteLine(" - The Queue is empty.");
                return (char)0;
            }
            return this.q[++getloc];
        }
}


2-ой вариант обработки возможной ошибки
Код


public class QueueEmptyException : ApplicationException
{
        public QueueEmptyException() : base(){}
        public QueueEmptyException(string str) : base(str){}
        
        public override string ToString()
        {
            return "\n" + this.Message;
        }    
    
}

public class Queue{
//...........................................
       public char get()
        {
            if(getloc == putloc)
                throw new QueueEmptyException(" - The Queue is empty.");
            return q[++getloc];
        }
}

очень хотелось бы услышать от опытных людей всегда ли стоит использовать обработку исключений при помощи try / catch / throw, т.к. прога из-за таких обработок оооооооочень тормозит.

Автор: ivashkanet 2.11.2006, 18:17
Все зависит от:
1) умеет ли класс, использующий твой метод (get -- тоже метод) правильно распознать произошла ошибка или нет.
В твоем случае это Console.WriteLine(" - The Queue is empty.") что вообще никто не словит (если сильно не захочет) и возврат нуля (который теперь исключен из допустимых символов).
2) кто должен отвечать за правильность данных. Тот кто вызывает либо тот кого вызывают. Если первый, то логичнее (и универсальнее) использовать throw (на случай если "профессор--лопух"), если нет, то возможно обработать исключение более мягко и уведомить вызывающий код задокументированным способом.
3) критично ли эта операция. Если это юзверьинтерфейс, то человек особо не заметит задержки произошедшей по вине throw (зато ошибаться будет часто). Если же это автоматическая обработка большого объема данных (даже если не большего), то нужно избежать как можно большего количества throw
4) может кто-нить еще добавит что-нить

ИМХО



Автор: agl 3.11.2006, 00:42
Цитата
1) умеет ли класс, использующий твой метод (get -- тоже метод) правильно распознать произошла ошибка или нет.
В твоем случае это Console.WriteLine(" - The Queue is empty.") что вообще никто не словит (если сильно не захочет) и возврат нуля (который теперь исключен из допустимых символов).

ну это не проблема, а просто пример =), в жизни можно сделать errflag например ну и задавать ему true если произошла ошибка.

Спасибо за ответ  smile , получила пищу для мыслительного процесса  smile 

Автор: archimed7592 3.11.2006, 05:19
Цитата(mr.DUDA @ 28.6.2006,  01:24)
З.Ы. могу только проконстатировать, что при постоянном использовании оператора trrow в своих приложениях, производительность серьёзно падает... Это действительно так.

mr.DUDA, а что ты имеешь ввиду под использованием throw? я вот просто подумываю, что будет работать быстрее:
Код
void abc1 (...)
{
     try
     {
         /* block #1 */
     }
     catch (Exception e)
     {
          throw new Exception (String.Format ("something failed in block #1 ({0})", e.Message));
     }
     try
     {
         /* block #2 */
     }
     catch (Exception e)
     {
          throw new Exception (String.Format ("something failed in block #2 ({0})", e.Message));
     }
/* ... */
     try
     {
         /* block #N */
     }
     catch (Exception e)
     {
          throw new Exception (String.Format ("something failed in block #N ({0})", e.Message));
     }
}

void abc2 (...)
{
     try
     {
         /* block #1 */
         /* block #2 */
         /* ... */
         /* block #N */
     }
     catch (Exception e)
     {
          throw new Exception (String.Format ("something failed in abc2 ({0})", e.Message));
     }
}

ты имеешь ввиду заключение кода в try...catch ухудшает быстродействие? или непосредственное исполнение оператора throw ухудшает бытродействие?

Автор: ivashkanet 3.11.2006, 10:20
archimed7592, непосредственное развертывание стека и поиск оператора который этот throw словит --- вот что замедляет быстродействие
Цитата(archimed7592 @  3.11.2006,  04:19 Найти цитируемый пост)
я вот просто подумываю, что будет работать быстрее:

Ну попробуй. Я, например, такого исследования не проводил. 
Хотя, на вскидку, ---- второй будет быстрее, ведь он словит эксэпшен в первом блоке, а в остальные даже не пойдет  smile 

Автор: mr.DUDA 3.11.2006, 10:21
Цитата(archimed7592 @  3.11.2006,  04:19 Найти цитируемый пост)
ты имеешь ввиду заключение кода в try...catch ухудшает быстродействие? или непосредственное исполнение оператора throw ухудшает бытродействие?

Генерация исключения (всё что происходит при этом - упаковка stack trace,  и поиск подходящего блока catch) - оверхед, и если злоупотреблять оператором throw, то в худшем случае оверхед может и до десятка процентов дорасти. Простой пример, без вложенных try..catch:

Код
using System;

class Program
{
    void MethodWithoutException()
    {
        // тут какое-то действие
        for (int i = 0; i < 10000; i++) ;
    }

    void MethodWithException()
    {
        // то же самое действие, плюс throw
        for (int i = 0; i < 10000; i++) ;
        throw new InvalidCastException("bla-bla-bla");
    }

    static void Main()
    {
        Program p = new Program();

        DateTime start1 = DateTime.Now;
        for (int i = 0; i < 10000; i++)
        {
            p.MethodWithoutException();
        }
        TimeSpan span1 = DateTime.Now - start1;

        DateTime start2 = DateTime.Now;
        for (int i = 0; i < 10000; i++)
        {
            try
            {
                p.MethodWithException();
            }
            catch (InvalidCastException)
            {
            }
        }
        TimeSpan span2 = DateTime.Now - start2;

        // выводит: MethodWithoutException: 265,625, MethodWithException: 656,25
        Console.WriteLine("MethodWithoutException: {0}, MethodWithException: {1}", span1.TotalMilliseconds, span2.TotalMilliseconds);
    }
}


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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)