C # «Использование» Синтаксис - PullRequest
43 голосов
/ 29 сентября 2008

Использует ли использование исключение или выбрасывает его? т.е.

using (StreamReader rdr = File.OpenText("file.txt"))
{
 //do stuff
}

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

Ответы [ 11 ]

61 голосов
/ 29 сентября 2008

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

StreadReader rdr = null;
try
{
    rdr = File.OpenText("file.txt");
    //do stuff
}
finally
{
    if (rdr != null)
        rdr.Dispose();
}

Таким образом, реальный ответ заключается в том, что он ничего не делает, за исключением того, что он добавлен в тело блока using. Он не справляется с этим или не отбрасывает его.

31 голосов
/ 29 сентября 2008

с помощью операторов не есть исключения.

Все, что делает «Using», это направляет ваш объект в блок using и автоматически вызывает Dispose () для объекта, когда он покидает блок.

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

16 голосов
/ 29 сентября 2008

using разрешает прохождение исключения. Это действует как попытка / окончание, когда окончание удаляет использованный объект. Таким образом, он подходит только для объектов, которые реализуют IDisposable.

5 голосов
/ 29 сентября 2008

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

try
{
    using (
        StreamReader rdr = File.OpenText("file.txt"))
    { //do stuff 
    }
}
catch (FileNotFoundException Ex)
{
    // The file didn't exist
}
catch (AccessViolationException Ex)
{
    // You don't have the permission to open this
}
catch (Exception Ex)
{
    // Something happened! 
}
3 голосов
/ 04 мая 2011

В вашем примере, если File.OpenText выбрасывает, Dispose будет не вызываться .

Если исключение происходит в //do stuff, будет вызываться Dispose .

В обоих случаях исключение обычно распространяется вне области действия, как это было бы без оператора using .

3 голосов
/ 29 сентября 2008

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

Однако следует обратить внимание на то, что если в выражении инициализации возникает исключение, то метод Dispose () не будет вызываться для переменной выражения. Это почти всегда то поведение, которое вы хотели бы, так как вы не хотите беспокоиться об удалении объекта, который на самом деле не был создан. Однако может возникнуть проблема в сложных обстоятельствах. То есть, если в конструкторе скрыты несколько инициализаций, а некоторые завершены успешно до того, как было сгенерировано исключение, вызов Dispose в этот момент может не произойти. Однако обычно это не проблема, поскольку конструкторы обычно просты.

2 голосов
/ 29 сентября 2008

using гарантирует *, что созданный объект будет расположен в конце блока, даже если выброшено исключение. Исключение составляет , а не . Тем не менее, вы должны быть осторожны с тем, что вы делаете, если вы пытаетесь поймать это самостоятельно. Поскольку любой код, который перехватывает исключение, находится за пределами блока контекста, определенного оператором using, ваш объект не будет доступен для этого кода.

* за исключением обычных подозреваемых, таких как сбой питания, ядерная катастрофа и т. Д.

2 голосов
/ 29 сентября 2008

Использование не мешает обработке исключений, кроме очистки материала в его области.

Он не обрабатывает исключения, но пропускает исключения.

2 голосов
/ 29 сентября 2008

Если вы специально не ловите исключение, оно выбрасывается в стек до тех пор, пока что-то не получится

1 голос
/ 29 сентября 2008

Вы можете представить , используя как try ... finally блок без блока catch. В блоке finally вызывается IDisposable.Dispose, и поскольку нет блока catch, все исключения генерируются в стеке.

...