public class EHClass
{
void ReadFile(int index)
{
// To run this code, substitute a valid path from your local machine
string path = @"c:\users\public\test.txt";
System.IO.StreamReader file = new System.IO.StreamReader(path);
char[] buffer = new char[10];
try
{
file.ReadBlock(buffer, index, buffer.Length);
}
catch (System.IO.IOException e)
{
Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message);
}
finally
{
if (file != null)
{
file.Close();
}
}
// Do something with buffer...
}
}
public static void RetryIfBusy(string server)
{
MailAddress from = new MailAddress("ben@contoso.com");
MailAddress to = new MailAddress("jane@contoso.com");
using (
MailMessage message = new MailMessage(from, to)
{
Subject = "Using the SmtpClient class.",
Body =
@"Using this feature, you can send an e-mail message from an application very easily."
})
{
message.CC.Add(new MailAddress("Notifications@contoso.com"));
using (SmtpClient client = new SmtpClient(server) {Credentials = CredentialCache.DefaultNetworkCredentials})
{
Console.WriteLine("Sending an e-mail message to {0} using the SMTP host {1}.", to.Address, client.Host);
try
{
client.Send(message);
}
catch (SmtpFailedRecipientsException ex)
{
foreach (var t in ex.InnerExceptions)
{
var status = t.StatusCode;
if (status == SmtpStatusCode.MailboxBusy || status == SmtpStatusCode.MailboxUnavailable)
{
Console.WriteLine("Delivery failed - retrying in 5 seconds.");
System.Threading.Thread.Sleep(5000); // Use better retry logic than this!
client.Send(message);
}
else
{
Console.WriteLine("Failed to deliver message to {0}", t.FailedRecipient);
// Do something better to log the exception
}
}
}
catch (SmtpException ex)
{
// Here, if you know what to do about particular SMTP status codes,
// you can look in ex.StatusCode to decide how to handle this exception
// Otherwise, in here, you at least know there was an email problem
}
// Note that no other, less specific exceptions are caught here, since we don't know
// what do do about them
}
}
}
try
{
someFunctionThatWorks();
functionThatThrowsAnException(); // As soon as this function throws an exception we are taken to the catch block
anotherFunction(); // <-- This line will never get executed
}
catch(Exception e)
{
// Here you can handle the exception, if you don't know how to handle it you should not be catching it
// After this you will not be taken back to the try block, you will go right to the finally block
}
finally
{
// Code here is always executed at the very end, regardless of whether an exception was thrown or not
}
5条答案
按热度按时间c90pui9n1#
如果您有(**注意:**这不是有效的C#,请参见下面的有效示例):
代码A将被执行。如果一切顺利(即A执行时没有抛出异常),它将进入finally,因此代码C将被执行。如果A执行时抛出异常,则它将进入B,然后最终进入C。
例如,下面是http://msdn.microsoft.com/en-us/library/dszsf989.aspx中的一个有效C#代码块:
使用try/catch/finally的原因是为了防止程序在某些代码出错时失败(上例中的A)。如果出现问题,您可以使用
catch
部分来捕获问题并执行一些有用的操作,例如通知用户,将异常记录到日志文件,重试或尝试其他您认为可能有效的操作,而不是最初尝试的操作。finally
用于确保执行某些清理。例如,在A中,您可能尝试打开并读取一个文件。如果打开成功,但读取失败,您将有一个打开的文件悬空。在这种情况下,您希望将其关闭,这将在finally
块中执行-此块始终得到执行,以确保文件的关闭。查看此处了解更多信息:
kmpatx3s2#
try ... catch
块用于捕获异常。在try
块中放入预期可能引发异常的代码。如果没有异常发生,那么
try
块中的代码按预期完成,如果有finally
块,那么接下来将执行该块。如果发生异常,则执行跳转到第一个匹配的
catch
块的开头。一旦该代码完成,则执行finally块(如果存在)。执行不会返回到try
块。jaql4c8m3#
您几乎不应该使用try/catch。
你应该只处理那些你可以纠正的
catch
异常,并且只在你期待它们的时候,否则,让调用者处理这个异常--或者不处理。如果使用,则首先执行任何
catch
子句-仅执行其中一个子句。然后,“最终”执行
finally
。这在很多地方都有更好的表述,但我还是会尝试。
并不修复异常。它隐藏了异常,这样问题就永远不会被修复。该代码不知道抛出了哪个异常,因为它会捕获所有异常,而且它没有做任何事情来纠正问题-它只是告诉用户一个礼貌的虚构。
事实上,上述代码应替换为以下代码:
这样,如果此方法的调用方知道如何修复特定问题,则调用方可以修复这些问题。您将不会从调用方删除该选项。
如果调用方不知道如何修复问题,则调用方也不应捕获异常。
下面是一个以合理方式使用异常的示例(来自MSDN),它是SmtpFailedRecipientsException Class文档中示例的修改形式。
请注意,这段代码使用try/catch来包围一小段代码。在try/catch块中,如果抛出SmtpException或SmtpFailedRecipientsException,我们知道该怎么做。例如,如果我们要捕获
IOException
,我们将不知道它的含义,也不知道该怎么做。不应该捕获任何实际上不知道如何更正的异常。除了可能向异常添加信息、记录它并重新抛出。huus2vyu4#
下面是一个例子:
62lalag45#
我想详细说明一下这一点,并使用场景扩展@icyrock.com答案,当您在catch块中重新抛出异常时,它将在执行堆栈的较低层处理...
我用下面的代码试了一下:
因此,当块A中没有异常时,序列如下(异常处理块永远不会命中):
当A块出现问题时,顺序如下:
换句话说,发生的异常首先由块B处理,然后执行finally子句,只有在异常被重新抛出并在执行堆栈的较低层处理之后(块D)。
请注意,我可能对.NET框架下实际发生的事情有错--我只是介绍了我观察到的结果:)