Ste*_*ger 6 c# recursion exception-handling
我有一个递归方法调用.当抛出任何异常时,我想看看,在递归调用堆栈中它发生了什么.我有一个字段,其中包含一个代表递归堆栈的"路径".
现在我想将路径信息添加到可能在递归调用中抛出的任何异常.
void Recursive(int x)
{
// maintain the recursion path information
path.Push(x);
try
{
// do some stuff and recursively call the method
Recursive(x + 6);
}
catch(Exception ex)
{
if (ex is RecursionException)
{
// The exception is already wrapped
throw;
}
// wrap the exception, this should be done only once.
// save the path and original exception to the wrapper.
throw new RecursionException(path.ToString(), ex);
}
finally
{
// maintain the recursion path information
path.Pop()
}
}
Run Code Online (Sandbox Code Playgroud)
它看起来太复杂了.不仅有一种方法.可能有二十个甚至更多的地方我必须编写这段代码.
有没有更简单的方法来实现这个?
编辑:要指出这一点:我想有一个更简单的情况,没有这样的开销递归调用方法,因为我有很多这样的递归调用,不仅有一个方法,还有几个方法递归地互相呼叫,这很复杂.
所以我想避免整个try-catch块,但我看不出任何解决方案.
对于我自己的代码中抛出的异常,这不是一个大问题,因为它可能包含从头开始的路径.但这是每个其他例外的问题.
编辑:异常需要包装在任何其他代码中,而不仅仅是在调用递归方法时:
try
{
int a = 78 / x; // DivisionByZeroExeption
Recursive(x + 6);
this.NullReference.Add(x); // NullReferenceException
}
Run Code Online (Sandbox Code Playgroud)
因此只包含对Recusive的调用不起作用.
有很多这样的方法,有不同的签名,做不同的事情,唯一常见的是异常处理.
只是简化(略微)异常处理:
void Recursive(int x)
{
// maintain the recursion path information
path.Push(x);
try
{
// do some stuff and recursively call the method
Recursive(x + 6);
}
catch( RecursionException )
{
throw;
}
catch( Exception )
{
throw new RecursionException(path.ToString(), ex);
}
finally
{
// maintain the recursion path information
path.Pop()
}
}
Run Code Online (Sandbox Code Playgroud)
如果对你有任何用处,你会收到带有异常的callstack信息,除此之外你可以把它写成一个片段,然后只需将它插入你需要重新使用的地方.
还有以下可能性,这将是缓慢但应该工作:
void DoStuff()
{
this.Recursive(1, this.RecursiveFunction1);
this.Recursive(2, this.RecursiveFunction2);
}
bool RecursiveFunction1(int x)
{
bool continueRecursing = false;
// do some stuff
return continueRecursing;
}
bool RecursiveFunction2(int y)
{
bool continueRecursing = false;
// do some other stuff here
return continueRecursing;
}
private void Recursive(int x, Func<int, bool> actionPerformer)
{
// maintain the recursion path information
path.Push(x);
try
{
// recursively call the method
if( actionPerformer(x) )
{
Recursive(x + 6, actionPerformer);
}
}
catch( RecursionException )
{
throw;
}
catch( Exception ex )
{
throw new RecursionException(path.ToString(), ex);
}
finally
{
// maintain the recursion path information
path.Pop();
}
}
Run Code Online (Sandbox Code Playgroud)
我认为您正在尝试在异常详细信息中包含递归路径以帮助调试。
\n\n尝试一下这个怎么样?
\n\npublic void Recursive(int x)\n{\n try\n {\n _Recursive(x)\n }\n catch\n { \n throw new RecursionException(path.ToString(), ex);\n clear path, we know we are at the top at this point\n }\n}\n\nprivate void _Recursive(int x)\n{\n // maintain the recursion path information\n path.Push(x);\n\n _Recursive(x + 6);\n\n //maintain the recursion path information\n //note this is not in a catch so will not be called if there is an exception\n path.Pop()\n}\nRun Code Online (Sandbox Code Playgroud)\n\n如果您正在使用线程等,您可能必须查看线程本地存储中的存储路径。
\n\n如果您不希望强制调用者处理 RecursionException,则可以将 \xe2\x80\x9cpath\xe2\x80\x9d 公开,以便调用者可以访问它。(正如埃里克·利珀特后来的回答)
\n\n或者,您可以在捕获异常时记录错误日志系统的路径,然后重新抛出异常。
\n\npublic void Recursive(int x)\n{\n try\n {\n _Recursive(x)\n }\n catch\n { \n //Log the path to your loggin sysem of choose\n //Maybe log the exception if you are not logging at the top \n // of your applicatoin \n //Clear path, we know we are at the top at this point\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这样做的优点是调用者根本不需要知道 \xe2\x80\x9cpath\xe2\x80\x9d。
\n\n这一切都取决于您的调用者的需求,不知何故,我认为您是此代码的调用者,因此我们没有必要尝试第二次猜测此级别的交易需要什么。
\n| 归档时间: |
|
| 查看次数: |
7138 次 |
| 最近记录: |