Да, Вы корректны - создают файл ресурсов. Когда Вы делаете это, Вы не должны "загружать" строку, на нее сошлются как Ресурс. WhateverStringYouDefined.
Я думаю, вы пытаетесь включить рекурсивный путь в детали исключения, чтобы облегчить отладку.
А как насчет того, чтобы попробовать это?
public void Recursive(int x)
{
try
{
_Recursive(x)
}
catch
{
throw new RecursionException(path.ToString(), ex);
clear path, we know we are at the top at this point
}
}
private void _Recursive(int x)
{
// maintain the recursion path information
path.Push(x);
_Recursive(x + 6);
//maintain the recursion path information
//note this is not in a catch so will not be called if there is an exception
path.Pop()
}
Если вы используете потоки и т. Д., Вам, возможно, придется посмотреть на сохранение пути в локальном хранилище потока.
Если вы не хотите заставлять вызывающего абонента иметь дело с RecursionException, вы можете сделать «путь» общедоступным, чтобы вызывающий мог получить к нему доступ. (Как позже ответил Эрик Липперт)
Или вы можете зарегистрировать путь к вашей системе регистрации ошибок, когда вы перехватили исключение, а затем просто повторно выбросить исключение.
public void Recursive(int x)
{
try
{
_Recursive(x)
}
catch
{
//Log the path to your loggin sysem of choose
//Maybe log the exception if you are not logging at the top
// of your applicatoin
//Clear path, we know we are at the top at this point
}
}
Это имеет то преимущество, что вызывающему абоненту вообще не нужно знать о «пути».
Все сводится к тому, что нужно вашему вызывающему,
Ваша проблема заключается в обработке исключений. Как правило, перенос исключения в собственное исключение является плохой идеей, потому что он накладывает бремя на вызывающего пользователя вашего кода, который вынужден обрабатывать ваше исключение. Вызывающий, который подозревает, что они могут, скажем, вызвать исключение «путь не найден», вызывая ваш код, не может заключить свой вызов в try-catch, который перехватывает IOException. Они должны перехватить ваше исключение RecursionException, а затем написать кучу кода, чтобы опросить его, чтобы определить, что это за исключение на самом деле. Бывают случаи, когда этот шаблон оправдан, но я не вижу, чтобы это один из них.
Дело в том, что вам действительно не нужно использовать здесь обработку исключений вообще. Вот некоторые желательные аспекты решения:
Хорошо, отлично, если это цели дизайна затем реализуйте это:
class C
{
private Stack<int> path
#if DEBUG
= new Stack<int>();
#else
= null;
#endif
public Stack<int> Path { get { return path; } }
[Conditional("DEBUG")] private void Push(int x) { Path.Push(x); }
[Conditional("DEBUG")] private void Pop() { Path.Pop(); }
public int Recursive(int n)
{
Push(n);
int result = 1;
if (n > 1)
{
result = n * Recursive(n-1);
DoSomethingDangerous(n);
}
Pop();
return result;
}
}
И теперь вызывающий может справиться с этим:
C c = new C();
try
{
int x = c.Recursive(10);
}
catch(Exception ex)
{
#if DEBUG
// do something with c.Path
Вы видите, что мы здесь делаем? Мы пользуемся преимуществом того факта, что исключение останавливает рекурсивный алгоритм на своем пути. Последнее, что мы хотим сделать, это очистить путь, добавив finally; мы хотим, чтобы всплывающие окна не отображались при исключении!
Имеет смысл?
class C
{
private Stack<int> path
#if DEBUG
= new Stack<int>();
#else
= null;
#endif
public Stack<int> Path { get { return path; } }
[Conditional("DEBUG")] private void Push(int x) { Path.Push(x); }
[Conditional("DEBUG")] private void Pop() { Path.Pop(); }
public int Recursive(int n)
{
Push(n);
int result = 1;
if (n > 1)
{
result = n * Recursive(n-1);
DoSomethingDangerous(n);
}
Pop();
return result;
}
}
И теперь вызывающий абонент может с этим справиться:
C c = new C();
try
{
int x = c.Recursive(10);
}
catch(Exception ex)
{
#if DEBUG
// do something with c.Path
Вы видите, что мы здесь делаем? Мы пользуемся преимуществом того факта, что исключение останавливает рекурсивный алгоритм на своем пути. Последнее, что мы хотим сделать, это очистить путь, добавив finally; мы хотим, чтобы всплывающие окна не отображались при исключении!
Имеет смысл?
class C
{
private Stack<int> path
#if DEBUG
= new Stack<int>();
#else
= null;
#endif
public Stack<int> Path { get { return path; } }
[Conditional("DEBUG")] private void Push(int x) { Path.Push(x); }
[Conditional("DEBUG")] private void Pop() { Path.Pop(); }
public int Recursive(int n)
{
Push(n);
int result = 1;
if (n > 1)
{
result = n * Recursive(n-1);
DoSomethingDangerous(n);
}
Pop();
return result;
}
}
И теперь вызывающий абонент может с этим справиться:
C c = new C();
try
{
int x = c.Recursive(10);
}
catch(Exception ex)
{
#if DEBUG
// do something with c.Path
Вы видите, что мы здесь делаем? Мы пользуемся преимуществом того факта, что исключение останавливает рекурсивный алгоритм на своем пути. Последнее, что мы хотим сделать, это очистить путь, добавив finally; мы хотим, чтобы всплывающие окна не отображались при исключении!
Имеет смысл?
Просто упрощаю (немного) обработку исключений:
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()
}
}
Вы получаете информацию о стеке вызовов с помощью Exception, если она вам нужна, кроме того, вы можете написать это как фрагмент, а затем просто вставить это там, где вам нужно для повторного использования.
Также существует следующая возможность, которая будет медленной, но должна работать:
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();
}
}
А как насчет того, чтобы выдернуть обработчик catch из рекурсивной функции и просто записать рекурсию без меньшей обработки?
void StartRecursion(int x)
{
try
{
path.Clear();
Recursive(x);
}
catch (Exception ex)
{
throw new RecursionException(path.ToString(), ex);
}
}
void Recursive(int x)
{
path.Push(x);
Recursive(x + 6);
path.Pop();
}
void Main()
{
StartRecursion(100);
}
void Recursive(int x)
{
// maintain the recursion path information
path.Push(x);
try
{
// do some stuff and recursively call the method
Recursive(x + 6);
}
finally
{
// maintain the recursion path information
path.Pop()
}
}
void Recursive2(int x)
{
try
{
Recursive(x);
}
catch()
{
// Whatever
}
}
Таким образом, вы обрабатываете только один раз, если возникает исключение, Recursive2 обрабатывает его, рекурсия прерывается.