使用throw in catch块这样好吗? [英] Is this good to use throw in catch block?

查看:70
本文介绍了使用throw in catch块这样好吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  public   class  TestInnerException 
{
public static void Main()
{
尝试
{
尝试
{
throw new ArgumentException();
}

catch (ArgumentException e)
{
// 确保此路径不存在
if (文件。存在( file://Bigsky//log.txt%22)%20 ==%20false)== false )
{
抛出新的FileNotFoundException(
文件未找到尝试将参数异常写入文件 ,e);
}
}
}

catch(异常) e)
{
Console.WriteLine(String.Concat(e.StackTrace,e.Message));

if(e.InnerException!= null)
{
Console.WriteLine(
内部例外 );
Console.WriteLine(String.Concat(e.InnerException.StackTrace,e.InnerException.Message));
}
}
Console.ReadLine();
}
}

解决方案

在很多情况下这样做很好,但不是这样的你来弄吧。重新投掷是为了用一些更具体的应用程序和具体的方法来取代抽象的,通用的,系统通用的异常。例如,在file-not-found条件的情况下,您可以创建指定文件名称的异常类型,向用户解释拥有此文件的目的并建议解决问题的步骤。异常数据可能包含文件名和某些机密信息。



为什么会这样?因为你不应该在本地捕获异常。您需要在有所需的地方处理异常,以有用的方式处理它们。我称之为能力点。在这一点上,您可能希望处理不仅在给定行中抛出异常,而且在其他行中抛出异常。您需要具有专门处理您创建的异常类型的句柄。完全依赖应用程序消息是一个常见的错误;尝试使用代表数据的字符串而不是数据的非常悲伤的现在数据谬误的一部分。



-SA

你的代码样本:



做对了:

投掷时FileNotFoundException包含ArgumentException作为内部异常。



可以做得更好:

你可以包含不能的文件名改为使用此构造函数找到:

  public  FileNotFoundException( string 消息,字符串 fileName,异常innerException)



(另请参阅解决方案2 )





异常处理的一些一般规则:

(不要认为这些要点是详尽无遗的。)



- 在捕获后抛出新的异常e,将先前的异常作为内部异常放入新异常中。 (一般来说。)



- 当重新抛出刚捕获的同样异常时,不要做抛出ex; (因为这会重置堆栈跟踪)但只需 throw;



- 不要混淆你的代码异常处理。仅为此目的捕获异常:1)记录2)尝试纠正失败3)在向其添加有关错误的其他信息后重新抛出 1 4)将其置于另一个例外中,以提供有关错误 1 的其他信息。否则只是让异常冒泡。唯一的强制性异常捕获是在程序的顶层(例如在Main() - 方法中)以便记录它。相反,这意味着:



- 不做任何事情就不要吞下异常。

(一般情况。可能有极少数例外情况,应该仔细考虑。)



- 如果可用,请使用在发生故障时不抛出异常但返回布尔成功标志的方法版本(例如Int32.TryParse(..)而不是Int32.Parse(..))。



- 不要(ab)使用控制流的异常。

(一般情况下,可能可以在本地使用,例如重新尝试读取用户输入,直到被接受为止。请参阅下面的第一条评论。)



- 例外应该是例外。不要为所发生的事情抛出异常。



1

异常消息不是异常可以携带的唯一信息。您可以在其他属性中存储有关错误的更多信息,例如:

数据属性 [ ^ ]

源属性 [ ^ ]

根据具体的Exception,可以更多,例如:

FileName-Property [ ^ ]
ParamName-Property [ ^ ] ArgumentException

当然,您可以创建自定义异常并为它们实现自定义属性以携带自定义错误信息。



关于异常处理的非常好的博客文章:

http:/ /www.hanselman.com/blog/GoodExceptionManagementRulesOfThumb.aspx [ ^ ]



异常和异常处理的MSDN:

https://msdn.microsoft.com/en-us/libr ary / ms173160%28v = vs.110%29.aspx [ ^ ]





编辑:谢尔盖·亚历山德罗维奇·克鲁科夫在下面的评论中提出建议。


R Hemanth问:



请你给出一个内部异常的例子而不使用多个try块...使用其他程序集的类作为一种方法

它与循环无关。以下是您的一个示例:

 枚举 FilePurpose {
InitialConfiguration,
ExpectedConfiguration,
ActualConfiguration,
// ...
}

internal class MyFileException:System.IO.FileNotFoundException {
internal MyFileException(
string fileName,
FilePurpose用途,
异常原文)
base 文件没有找到,fileName,original){
this .Purpose = purpose;
}
内部 FilePurpose目的{ get ; private set ; }
}



  class 示例{ 
void Test(){
FilePurpose purpose = FilePurpose.ExpectedConfiguration;
尝试 {
// 尝试打开一些文件
} catch (System.IO.FileNotFoundException e){
throw new MyFileException(e.FileName,purpose,e);
}
}
}



这个例子有点人为,但我无法发明更简单的东西来说明这个想法:你创建更多语义类型的异常并向一些更普遍的异常类型的实例添加一些新信息,在这种情况下,目的,因为你的代码更好地了解特定用途。



你明白了吗?



-SA


public class TestInnerException
{
    public static void Main()
    {
        try
        {
            try
            {
                throw new ArgumentException();
            }

            catch (ArgumentException e)
            {
                //make sure this path does not exist
                if (File.Exists("file://Bigsky//log.txt%22)%20==%20false) == false)
                {
                    throw new FileNotFoundException("File Not found when trying to write argument exception to the file", e);
                }
            }
        }

        catch (Exception e)
        {
            Console.WriteLine(String.Concat(e.StackTrace, e.Message));

            if (e.InnerException != null)
            {
                Console.WriteLine("Inner Exception");
                Console.WriteLine(String.Concat(e.InnerException.StackTrace, e.InnerException.Message));
            }
        }
        Console.ReadLine();
    }
}

解决方案

It's good to do in many cases, but not the way you do it. Re-throwing is done to replace abstract, generic, "system-universal" exceptions with some more application-specific and concrete. For example, in the case of file-not-found condition, you could create your exception type which specifies the name of the file, explains the user the purpose of having this file and suggests the steps to fix the problem. The exception data can include file name and perhaps some classified information.

Why so? Because you should not catch exception too locally. You need to handle exception at the places where you have all you need to handle them in a useful way. I call them "competency points". At such point, you may want to handle exception thrown not only in the given line, but in some others. You would need to have a handle working specifically with the exception type you created. It's a common mistake to rely exclusively on the application message; a part of very sorrowful present-data fallacy of trying to work with strings representing data, instead of data.

—SA


Your code-sample:

Done right:
When throwing the FileNotFoundException you include the ArgumentException as an inner exception.

Could be done better:
You could include the name of the file that could not be found by using this constructor instead:

public FileNotFoundException(string message, string fileName, Exception innerException)


(Please also refer to solution 2)


Some general rules for Exception-handling:
(Don't consider these points as exhaustive.)

- When throwing a new exception after catching one, put the previous exception as an inner exception into the new one. (In general.)

- When re-throwing the same exception as just caught, dont do throw ex; (because that will reset the stacktrace) but simply throw;

- Don't clutter your code with exception-handling. Only catch exceptions for these purposes: 1) Logging 2) Trying to remedy the failure 3) Re-throwing it after adding additional information about the error to it1 4) Putting it into another exception in order to provide additional information about the error1. Otherwise just let exceptions "bubble up". The only "mandatory" exception-catching would be at the top-level of your program (e.g. in the Main()-method) in order to log it. In reverse, this means:

- Don't swallow exceptions without doing anything.
(In general. There might be rare exceptions, which should be considered carefully.)

- When available, use versions of methods that don't throw an exception in case of failure but return a boolean success-flag (e.g. Int32.TryParse(..) instead of Int32.Parse(..)).

- Don't (ab)use exceptions for control-flow.
(In general. It might be o.k. locally, e.g. for re-attempting to read user-input until it is accepted. Please see the first comment below.)

- Exceptions should be exceptional. Don't throw exceptions for things that happen all the time.

1 :
The message of the exception is not the only information that an exception can carry. You can store further information about an error in other properties, e.g.:
The Data-Property[^]
The Source-Property[^]
Depending on the concrete Exception, there can be more, e.g.:
The FileName-Property[^] of FileNotFoundException
The ParamName-Property[^] of ArgumentException
And of course you can create your custom Exceptions and implement custom properties for them to carry your custom error-information.

A very good blog-post about exception-handling:
http://www.hanselman.com/blog/GoodExceptionManagementRulesOfThumb.aspx[^]

MSDN on exceptions and exception-handling:
https://msdn.microsoft.com/en-us/library/ms173160%28v=vs.110%29.aspx[^]


Edit: Incorporated suggestions from Sergey Alexandrovich Kryukov's comment below.


R Hemanth asked:


Will u please give an example of inner exceptions without using multiple try blocks ...using class of other assembly which as one method

It has nothing to do with loops. Here is one example for you:

enum FilePurpose {
    InitialConfiguration,
    ExpectedConfiguration,
    ActualConfiguration,
    //...
}

internal class MyFileException : System.IO.FileNotFoundException {
    internal MyFileException(
        string fileName,
        FilePurpose purpose,
        Exception original)
    : base("File not found", fileName, original){
        this.Purpose = purpose;
    }
    internal FilePurpose Purpose { get; private set; }
}


class Sample {
    void Test() {
        FilePurpose purpose = FilePurpose.ExpectedConfiguration;
        try {
            // try to open some file
        } catch (System.IO.FileNotFoundException e) {
            throw new MyFileException(e.FileName, purpose, e);
        }
    }
}


This example is a bit artificial, but I could not invent something simpler to illustrate the idea: you create "more semantic" type of exception and add some new information to the instance of some "more universal" exception type, in this case, "purpose", because "your code knows particular purpose better".

Are you getting the idea?

—SA


这篇关于使用throw in catch块这样好吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆