繁体   English   中英

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

[英]Resharper Exception rethrow possibly intended

考虑一下这种方法(原谅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;
    }
}

在resharper中,我收到一条警告“throw e”行说“异常重新抛出可能意图”。 但显然在这种情况下,这不是意图,因为e可以包装在ChuckNorrisException中,如果我只是使用“throw”,那么包装的异常就不会被抛出。

我知道我可以抑制resharper警告,但是如果我没有弄错的话,它会在所有情况下关闭。 我只是想知道是否还有其他人遇到过此事。 我发现的唯一解决方法是创建另一个异常变量(例如e2),然后抛出它。 这可能是我能在这里做的最好的。 似乎resharper可以检测到这个问题并且足够聪明,知道如果e被修改,那么抛出e就可以了。

谢谢。

[编辑]对不起,我忘记了一步。 在抛出之前,我需要记录异常,所以我不能这样做:

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

我要做:

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

也许我不理解这个问题,所以如果我有错误的结论,请纠正我。

这里有两种情况:

  1. 首先是你抓住原来的例外。 然后将其作为内部异常包装在新的异常实例中,然后抛出新的异常。 在这种情况下不会丢失任何信息(内部异常保留所有信息),因此不会给出警告。

  2. 第二个是你抓住并重新抛出原始异常。 如果你重新抛出,你永远不应该使用“throw e”,因为它会篡改堆栈跟踪。 这就是ReSharper打印警告的原因。 要重新抛出捕获的异常,您应该自己使用“throw”关键字。

这个问题的答案解释得比我好。 由于微妙的副作用以及使这个细节错误的人数众多,我个人认为重新抛出的语法是有缺陷的。

无论如何,这是对你收到警告的原因的描述。 以下是我要做的事情:

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);
}

*编辑 - 如果您需要记录异常,您可以执行此类操作。 注意:这是我首选的解决方案,因为我认为它读起来更好,并且不像自己查询异常类型那样包含错误:

// 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
}

另一种选择是:

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;
}

这将与您发布的代码具有相同的效果,不应导致警告。

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