简体   繁体   English

Resharper异常重新抛出可能是有意的

[英]Resharper Exception rethrow possibly intended

Consider this method (pardon the sad attempt at Chuck Norris humor :) ): 考虑一下这种方法(原谅Chuck Norris幽默的悲惨尝试:)):

public class ChuckNorrisException : Exception
{
    public ChuckNorrisException()
    {
    }

    public ChuckNorrisException(string message)
        : base(message)
    {
    }

    public ChuckNorrisException(string message, Exception cause)
        : base(message, cause)
    {
    }

    protected ChuckNorrisException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }
}

static void ExceptionTest(double x)
{
    try
    {
        double y = 10 / x;
        Console.WriteLine("quotient = " + y);
    }
    catch (Exception e)
    {
        e = e is DivideByZeroException ? new ChuckNorrisException("Only Chuck Norris can divide by 0!", e) :
            e;
        throw e;
    }
}

In resharper, I get a warning on the "throw e" line saying "Exception rethrow possibly intended". 在resharper中,我收到一条警告“throw e”行说“异常重新抛出可能意图”。 But obviously in this case that's not the intention, since e could be wrapped in ChuckNorrisException, and if I just use "throw", that wrapped exception wouldn't get thrown. 但显然在这种情况下,这不是意图,因为e可以包装在ChuckNorrisException中,如果我只是使用“throw”,那么包装的异常就不会被抛出。

I know I can suppress the resharper warning, but then it will be turned off for all scenarios if I'm not mistaken. 我知道我可以抑制resharper警告,但是如果我没有弄错的话,它会在所有情况下关闭。 I just wondered if anybody else had encountered this. 我只是想知道是否还有其他人遇到过此事。 The only workaround I've found is to make another exception variable (e2, for example), and throw that. 我发现的唯一解决方法是创建另一个异常变量(例如e2),然后抛出它。 That may be the best I can do here. 这可能是我能在这里做的最好的。 Seems like resharper could detect this issue though and be smart enough to know that if e is modified, then throw e is ok. 似乎resharper可以检测到这个问题并且足够聪明,知道如果e被修改,那么抛出e就可以了。

Thanks. 谢谢。

[EDIT] Sorry, I forgot a step. [编辑]对不起,我忘记了一步。 Before the throw, I need to log the exception, so I can't just do: 在抛出之前,我需要记录异常,所以我不能这样做:

e = e is DivideByZeroException ? new ChuckNorrisException("Only Chuck Norris can divide by 0!", e) :
            e;
throw e;

I have to do: 我要做:

e = e is DivideByZeroException ? new ChuckNorrisException("Only Chuck Norris can divide by 0!", e) :
            e;
LogException(e);
throw e;

Maybe I'm not understanding the question, so please correct me if I've got the wrong end of the stick. 也许我不理解这个问题,所以如果我有错误的结论,请纠正我。

There's two cases going on here: 这里有两种情况:

  1. The first is that you catch the original exception. 首先是你抓住原来的例外。 You then wrap it in a new exception instance as the inner exception, then throw the new one. 然后将其作为内部异常包装在新的异常实例中,然后抛出新的异常。 No information is lost in this case (the inner exception preserves all information), so no warning is given. 在这种情况下不会丢失任何信息(内部异常保留所有信息),因此不会给出警告。

  2. The second is that you catch and re-throw the original exception. 第二个是你抓住并重新抛出原始异常。 If you re-throw, you should never use "throw e", as it will tamper with the stack trace. 如果你重新抛出,你永远不应该使用“throw e”,因为它会篡改堆栈跟踪。 This is why ReSharper is printing a warning. 这就是ReSharper打印警告的原因。 To re-throw the caught exception, you should use the "throw" keyword on its own. 要重新抛出捕获的异常,您应该自己使用“throw”关键字。

The answer to this question explains it better than I can. 这个问题的答案解释得比我好。 Due to the subtle side effects and the sheer number of people who get this detail wrong, I personally view the re-throw syntax as flawed. 由于微妙的副作用以及使这个细节错误的人数众多,我个人认为重新抛出的语法是有缺陷的。

Anyway that's a description of why you're getting a warning. 无论如何,这是对你收到警告的原因的描述。 Here's what I'd do about it instead: 以下是我要做的事情:

catch(DivideByZeroException e)
{
    // we don't catch any other exceptions because we weren't
    // logging them or doing anything with the exception before re-throwing
    throw new ChuckNorrisException("Useful information", e);
}

*Edit -- if you need to log exceptions, you can just do something like this instead. *编辑 - 如果您需要记录异常,您可以执行此类操作。 Note: This is my preferred solution as I think it reads better and is less likely to contain an error than querying for exception types yourself: 注意:这是我首选的解决方案,因为我认为它读起来更好,并且不像自己查询异常类型那样包含错误:

// catch most specific exception type first
catch(DivideByZeroException e)
{
    Log(e); 
    throw new ChuckNorrisException("Useful information", e);
} 
catch(Exception e) // log & re-throw all other exceptions
{
    Log(e);
    throw; // notice this is *not* "throw e"; this preserves the stack trace
}

Another alternative would be: 另一种选择是:

catch(Exception e)
{
    Log(e);
    if(e is DivideByZeroException)
    {
        // wrap + throw the exception with our new exception type
        throw new ChuckNorrisException("useful info", e);
    }

    // re-throw the original, preserving the stack trace
    throw;
}

This will have the same effect as the code you have posted and should not cause the warning. 这将与您发布的代码具有相同的效果,不应导致警告。

catch (DivideByZeroException de)
    {
        throw new ChuckNorrisException("Only Chuck Norris can divide by 0!", de);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM