Я понимаю, как выгода попытки работает и как попытка наконец работает, но я использую тех, которые (обычно) в двух совершенно других сценариях:
using
в C# и VB), главным образом используется вокруг некоторого блока кода среднего размера, который использует некоторый ресурс, который должен быть расположен правильно.По моему опыту, случаи, где try-catch-finally был бы соответствующим, т.е. где блок, в котором я хочу поймать некоторое конкретное исключение, является точно тем же блоком, в котором я использую некоторый доступный ресурс, чрезвычайно редки. Все же разработчики языка C#, VB и Java, кажется, полагают, что это очень общий сценарий; разработчики VB даже думают о добавляющей выгоде к using
.
Я пропускаю что-то? Или я просто чрезмерно педантичен со своим строгим использованием выгоды попытки?
Править: Разъясниться: Мой код обычно похож на это (функции, развернутые для ясности):
Try
do something
Aquire Resource (e.g. get DB connection)
Try
do something
Try
do something that can fail
Catch SomeException
handle expected error
do something else...
Finally
Close Resource (e.g. close DB connection)
do something
Catch all
handle unexpected errors
который просто, кажется, имеет намного больше смысла, чем помещение любого из этих двух завоевывает популярность тот же уровень как наконец только для предотвращения добавления отступа.
Цитата из MSDN
Обычное использование catch и finally вместе - это получение и использование ресурсов в блоке try, рассмотрение исключительные обстоятельства в блоке catch блоке, и освободить ресурсы в блоке finally.
Чтобы было еще понятнее, представьте себе код, который вы хотите выполнить, в 99% случаев он выполняется отлично, но где-то в куске может возникнуть ошибка, вы не знаете где, а созданные ресурсы стоят дорого.
Чтобы быть уверенным на 100%, что ресурсы будут утилизированы, вы используете блок finally, однако вы хотите точно определить тот 1% случаев, когда произошла ошибка, поэтому вы можете установить логирование в секции catch-ing.
Это очень распространенный сценарий.
Редактирование - практический пример
Здесь есть несколько хороших примеров: SQL-транзакции с классом SqlTransaction. Это всего лишь один из многих способов использования Try, Catch & Finally, и он демонстрирует его очень хорошо, хотя using(var x = new SqlTranscation)
может быть эффективным в некоторых случаях.
Так что вот так.
var connection = new SqlConnection();
var command = new SqlCommand();
var transaction = connection.BeginTransaction();
command.Connection = connection;
command.Transaction = transaction;
А вот дальше начинается самое интересное
///
/// Try to drop a database
///
try
{
connection.Open();
command.CommandText = "drop database Nothwind";
command.ExecuteNonQuery();
}
Итак, представим, что вышеописанное по какой-то причине не работает и возникает исключение
///
/// Due to insufficient priviligies we couldn't do it, an exception was thrown
///
catch(Exception ex)
{
transaction.Rollback();
}
Транзакция будет откачена! Помните, что изменения, внесенные в объекты внутри try/catch, не будут откачены, даже если вы вложите их в using!
///
/// Clean up the resources
///
finally
{
connection.Close();
transaction = null;
command = null;
connection = null;
}
Теперь ресурсы очищены!
Нет ничего плохого во вложении блоков try / catch / finally. На самом деле я использую это довольно часто. Т.е. когда я использую какой-либо ресурс, который необходимо удалить или закрыть, но мне нужен только один блок catch вокруг более крупного блока кода, который необходимо прервать, если внутри него возникнет какая-то ошибка.
try {
// some code
SomeResource res = new SomeResource();
try {
res.use();
} finally {
res.close();
}
// some more code
} catch( Exception ex ) {
handleError( ex );
}
Это закрывает ресурс как можно раньше в любом случае (ошибка или нет), но по-прежнему обрабатывает все возможные ошибки при создании или использовании ресурса в одном блоке catch.
Не ответ на ваш вопрос, а забавный факт.
Реализация компилятора C # от Microsoft на самом деле не может обрабатывать try-catch-finally. Когда мы анализируем код
try { Foo() }
catch(Exception e) { Bar(e); }
finally { Blah(); }
, мы фактически делаем вид, что код был написан
try
{
try { Foo(); }
catch(Exception e) { Bar(e); }
}
finally { Blah(); }
Таким образом, остальная часть компилятора - семантический анализатор, средство проверки достижимости, генератор кода и т. Д. - только когда-либо имеет дело с попыткой-поймать и попробовать-наконец, никогда не попробовать-поймать-наконец. На мой взгляд, это было немного глупо, но оно работает.
Пример:
Try
Get DB connection from pool
Insert value in table
do something else...
Catch
I have an error... e.g.: table already contained the row I was adding
or maybe I couldn't get the Connection at all???
Finally
if DB connection is not null, close it.
Более "обычного" примера и не придумаешь. Жаль, что некоторые люди все еще забывают поместить закрытое соединение в Finally, где ему и место, а не в блок Try... :(
Четыре буквы.
Они функционально идентичны, просто написаны по-разному.
Если вы имеете в виду, как снять «проверенное» состояние со всех флажков:
$('input:checkbox').removeAttr('checked');
-121--851558- Я бы почти всегда использовал try-catch-finaly в случаях, когда вам нужно что-то утилизировать во всех случаях, и вы используете этот случай для регистрации ошибки и/или информирования пользователя.
Я часто пишу код, который выглядит примерно так:
Handle h = ...
try {
// lots of statements that use handle
} catch (SomeException ex) {
// report exception, wrap it in another one, etc
} catch (SomeOtherException ex) {
// ...
} finally {
h.close();
}
Так что, возможно, вы просто слишком педантичны... например, ставя try / catch вокруг отдельных утверждений. (Иногда это необходимо, но, по моему опыту, обычно не нужно быть таким мелочным)
.Имеется перегрузка группы метод, который принимает IEqualityComparer как параметр, но есть ли эквивалентно использованию предложения group?
Вы всегда можете сгруппировать по анонимному типу, если вам просто нужно быстрое встроенное решение и вы не беспокоитесь о том, чтобы набрать точный тип для ключей:
var grouped =
from it in items
group it by new {it.Coordinate.Latitude, it.Coordinate.Longitude};
-121--2793608- Если вам не нужно менять Look and Feel, не могли бы вы попробовать поставить UIManager.setLookAndFeel
Это, кажется, работает для меня, хотя я не в состоянии понять, почему это не сработает путь вы настроили это.
-121--335519-Другое использование состоит в удалении дескриптора файла во вложении электронной почты при использовании объектов почты System.Web.Mail для отправки электронной почты. Я узнал это, когда мне пришлось программно открыть Crystal Report, сохранить его на диске, прикрепить к электронной почте, а затем удалить с диска. Явный .Dispose () был необходим в Finally, чтобы убедиться, что я могу удалить его, особенно в случае выброшенного исключения.
По моему опыту, случаи, когда try-catch-finally были бы уместными, т.е. когда блок, в котором я хочу поймать какое-то конкретное исключение, является точно таким же блоком, в котором Пользуюсь каким-то одноразовым ресурсом, встречаются крайне редко. Тем не менее, разработчики языков C #, VB и Java, похоже, считают это очень распространенным сценарием; дизайнеры VB даже думают о добавлении уловки в using.
вы:
try {
//use resource
} catch (FirstException e) {
// dispose resource
// log first exception
} catch (SecondException e) {
// dispose resource
// log first exception
} catch (ThirdException e) {
// dispose resource
// log first exception
}
я:
try {
//use resource
} catch (FirstException e) {
// log first exception
} catch (SecondException e) {
// log first exception
} catch (ThirdException e) {
// log first exception
} finally {
// dispose resource
}
чувствуете сопротивление?)
Это может облегчить это
using HWND = System.IntPtr;
Затем используйте HWND в своем pInvoke..., чтобы облегчить чтение и сохранить его «таким же», как подпись pinvoke.
Надеюсь, что это поможет, С уважением, Том.
-121--4378620- Этот код выдаст арифметическое исключение
:
int x = 1 / 0;
-121--2843426- Я думаю, что вы совершенно правы. От. Руководство по проектированию Net Framework , написанное некоторыми ведущими архитекторами Microsoft:
НЕ . Исключения должны часто разрешается распространять вверх стек вызовов.
В хорошо написанном коде попробуйте окончательно [или использование] встречается гораздо чаще, чем попробовать-поймать. Это может показаться сначала контринтуитив, но поймать блоки не нужны в удивительном количество дел. С другой стороны, вы всегда должны учитывать, try-finally [или использование] может быть полезным для очистки.
стр. 230 раздел 7,2
Как насчет чего-то вроде:
Dim mainException as Exception = Nothing Try ... Start a transaction ... confirm the transaction Catch Ex as Exception mainException = Ex Throw Finally Try ... Cleanup, rolling back the transaction if not confirmed Catch Ex as Exception Throw New RollbackFailureException(mainException, Ex) End Try End Try
Предположим, что RollbackFailureException включает поле "OriginalException", а также "InnerException", и принимает параметры для обоих. Не хочется скрывать тот факт, что во время отката произошло исключение, но и не хочется терять исходное исключение, которое вызвало откат (и могло бы дать подсказку о том, почему произошел откат).