C# 何时使用 try/catch 块?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1722964/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 20:15:56  来源:igfitidea点击:

When to use try/catch blocks?

c#.netexception-handlingtry-catch

提问by fieldingmellish

I've done my reading and understand what a Try/Catch block does and why it's important to use one. But I'm stuck on knowing when/whereto use them. Any advice? I'll post a sample of my code below in hopes that someone has some time to make some recommendations for my example.

我已经阅读并理解了 Try/Catch 块的作用以及为什么使用它很重要。但我一直不知道何时/何地使用它们。有什么建议吗?我将在下面发布我的代码示例,希望有人有时间为我的示例提出一些建议。

    public AMPFileEntity(string filename)
    {
        transferFileList tfl = new transferFileList();
        _AMPFlag = tfl.isAMPFile(filename);
        _requiresPGP = tfl.pgpRequired(filename);
        _filename = filename.ToUpper();
        _fullSourcePathAndFilename = ConfigurationSettings.AppSettings.Get("sourcePath") + _filename;
        _fullDestinationPathAndFilename = ConfigurationSettings.AppSettings.Get("FTPStagePath") + _filename;
        _hasBeenPGPdPathAndFilename = ConfigurationSettings.AppSettings.Get("originalsWhichHaveBeenPGPdPath");
    }


    public int processFile()
    {

        StringBuilder sb = new StringBuilder();
        sb.AppendLine(" ");
        sb.AppendLine("    --------------------------------");
        sb.AppendLine("     Filename: " + _filename);
        sb.AppendLine("     AMPFlag: " + _AMPFlag);
        sb.AppendLine("     Requires PGP: " + _requiresPGP);
        sb.AppendLine("    --------------------------------");
        sb.AppendLine(" ");

        string str = sb.ToString();
        UtilityLogger.LogToFile(str);
        if (_AMPFlag)
        {
            if (_requiresPGP == true)
            {
                encryptFile();
            }
            else
            {
                UtilityLogger.LogToFile("This file does not require encryption. Moving file to FTPStage directory.");
                if (File.Exists(_fullDestinationPathAndFilename))
                {
                    UtilityLogger.LogToFile(_fullDestinationPathAndFilename + " alreadyexists. Archiving that file.");
                    if (File.Exists(_fullDestinationPathAndFilename + "_archive"))
                    {
                        UtilityLogger.LogToFile(_fullDestinationPathAndFilename + "_archive already exists.  Overwriting it.");
                        File.Delete(_fullDestinationPathAndFilename + "_archive");
                    }
                    File.Move(_fullDestinationPathAndFilename, _fullDestinationPathAndFilename + "_archive");
                }
                File.Move(_fullSourcePathAndFilename, _fullDestinationPathAndFilename);
            }
        }
        else
        {
            UtilityLogger.LogToFile("This file is not an AMP transfer file. Skipping this file.");
        }

            return (0);
    }


    private int encryptFile()
    {

        UtilityLogger.LogToFile("This file requires encryption.  Starting encryption process.");


        // first check for an existing PGPd file in the destination dir.  if exists, archive it - otherwise this one won't save.  it doesn't overwrite.
        string pgpdFilename = _fullDestinationPathAndFilename + ".PGP";



        if(File.Exists(pgpdFilename))
        {
            UtilityLogger.LogToFile(pgpdFilename + " already exists in the FTPStage directory.  Archiving that file." );
            if(File.Exists(pgpdFilename + "_archive"))
            {
                UtilityLogger.LogToFile(pgpdFilename + "_archive already exists.  Overwriting it."); 
                File.Delete(pgpdFilename + "_archive");
            }
            File.Move(pgpdFilename, pgpdFilename + "_archive"); 
        }

        Process pProc = new Process();
        pProc.StartInfo.FileName = "pgp.exe";

        string strParams = @"--encrypt " + _fullSourcePathAndFilename + " --recipient infinata --output " + _fullDestinationPathAndFilename + ".PGP";

        UtilityLogger.LogToFile("Encrypting file.  Params: " + strParams);
        pProc.StartInfo.Arguments = strParams;
        pProc.StartInfo.UseShellExecute = false;
        pProc.StartInfo.RedirectStandardOutput = true;
        pProc.Start();
        pProc.WaitForExit();

        //now that it's been PGPd, save the orig in 'hasBeenPGPd' dir
        UtilityLogger.LogToFile("PGP encryption complete.  Moving original unencrypted file to " +  _hasBeenPGPdPathAndFilename); 
        if(File.Exists(_hasBeenPGPdPathAndFilename + _filename + "original_which_has_been_pgpd"))
        {
            UtilityLogger.LogToFile(_hasBeenPGPdPathAndFilename + _filename + "original_which_has_been_pgpd already exists.  Overwriting it.");
            File.Delete(_hasBeenPGPdPathAndFilename + _filename + "original_which_has_been_pgpd");
        }
            File.Move(_fullSourcePathAndFilename, _hasBeenPGPdPathAndFilename + _filename + "original_which_has_been_pgpd");

        return (0);

    }
}

}

}

采纳答案by Yuval Adam

The basic rule of thumb for catching exceptions is to catch exceptions if and only ifyou have a meaningful way of handling them.

捕获异常的基本经验法则是当且仅当您有一种有意义的方法来处理异常时才捕获异常

Don'tcatch an exception if you're only going to log the exception and throw it up the stack. It serves no meaning and clutters code.

如果您只想记录异常并将其抛出堆栈,请不要捕获异常。它没有任何意义并且使代码混乱。

Docatch an exception when you are expecting a failure in a specific part of your code, and if you have a fallback for it.

难道当你在你的代码的特定部分期待一个失败捕获异常,如果你有这方面的后备。

Of course you always have the case of checked exceptions which require you to use try/catch blocks, in which case you have no other choice. Even with a checked exception, make sure you log properly and handle as cleanly as possible.

当然,您总是会遇到需要使用 try/catch 块的检查异常情况,在这种情况下,您别无选择。即使有已检查的异常,请确保正确记录并尽可能干净地处理。

回答by osij2is

I was taught to use try/catch/finally for any methods/classes where multiple errors could occur and that you can actually handle. Database transactions, FileSystem I/O, streaming, etc. Core logic usually doesn't require try/catch/finally.

我被教导将 try/catch/finally 用于任何可能发生多个错误并且您可以实际处理. 数据库事务、文件系统 I/O、流等。核心逻辑通常不需要 try/catch/finally。

The great part about try/catch/finally is that you can have multiple catches so that you can create a series of exception handlers to deal with veryspecific error or use a general exception to catch whatever errors you don't see coming.

try/catch/finally 的重要部分是您可以有多个捕获,以便您可以创建一系列异常处理程序来处理非常具体的错误或使用一般异常来捕获您看不到的任何错误。

In your case, you're using File.Exists which is good, but their maybe another problem with the disk that may throw another error that File.Exists cannot handle. Yes, it's a boolean method, but say the File is locked and what happens if you try to write to it? With the catch, you can plan for a rare scenario, but without try/catch/finally, you may be exposing the code to completely unforeseen conditions.

在您的情况下,您使用的是 File.Exists,这很好,但它们可能是磁盘的另一个问题,可能会引发 File.Exists 无法处理的另一个错误。是的,这是一个布尔方法,但是如果文件被锁定,如果您尝试写入它会发生什么?有了 catch,您可以为罕见的情况做计划,但如果没有 try/catch/finally,您可能会将代码暴露在完全无法预料的情况下。

回答by o.k.w

The other guys have given quite a number of good pointers and references.

其他人给出了很多很好的指示和参考。

My input is a short one:
When to use it is one thing, equally or more importanly is how to use it properly.

我的意见很简短:
何时使用它是一回事,同样或更重要的是如何正确使用它。

PS: "it" is refeings to "trying-catching exceptions".

PS:“它”是对“尝试捕获异常”的引用。

回答by Ryan Elkins

Like some others have said, you want to use try catch block around code that can throw an ExceptionAND that you are prepared to deal with.

就像其他人所说的那样,您希望在可能抛出Exception您准备处理的AND 的代码周围使用 try catch 块。

For you particular examples, File.Deletecan throw a number of exceptions, including IOException, UnauthorizedAccessExceptionas well as others. What would you want your application to do in those situations? If you try to delete the file but someone somewhere else is using it, you will get an IOException.

对于您的特定示例,File.Delete可以抛出许多异常,包括IOExceptionUnauthorizedAccessException以及其他。在这些情况下,您希望您的应用程序做什么?如果您尝试删除该文件但其他人正在使用它,您将得到一个IOException.

try
{    
    File.Delete(pgpdFilename + "_archive")
}
catch(IOException)
{
    UtilityLogger.LogToFile("File is in use, could not overwrite.");
   //do something else meaningful to your application
   //perhaps save it under a different name or something
}

Also keep in mind that if this does fail, then the File.Moveyou do outside of your ifblock next will also fail (again to an IOException- since the file was not deleted it is still there which will cause the move to fail).

还要记住,如果这确实失败了,那么File.Moveif接下来在块之外执行的操作也将失败(再次失败IOException- 由于文件没有被删除,它仍然存在,这将导致移动失败)。