这是goto的明确用法吗?

Jam*_*ney 7 c# goto

只是想知道这是否被认为是在C#中明确使用goto:

IDatabase database = null;

LoadDatabase:
try
{
    database = databaseLoader.LoadDatabase();
}
catch(DatabaseLoaderException e)
{
    var connector = _userInteractor.GetDatabaseConnector();
    if(connector == null)
        throw new ConfigException("Could not load the database specified in your config file.");
    databaseLoader = DatabaseLoaderFacade.GetDatabaseLoader(connector);
    goto LoadDatabase;
}
Run Code Online (Sandbox Code Playgroud)

我觉得这样可以,因为代码片段很小,应该有意义.当你想在处理异常后重试操作时,人们通常会从这样的错误中恢复吗?

编辑:那很快.回答几个问题并稍微澄清一下 - 这是一个过程的一部分,本质上是从一个不同类型的项目转换而来._userInteractor.GetDatabaseConnector()调用是确定用户是否要重试的部分(可能使用与正在加载的配置中的数据库不同的数据库).如果它返回null,则表明没有指定新的数据库连接,操作应该完全失败.

我不知道为什么我没有考虑使用while循环.它必须太接近下午5点.

编辑2:我查看了LoadDatabase()方法,DatabaseLoaderException如果失败则会抛出一个.我已经更新了上面的代码来捕获异常而不是异常.

编辑3:普遍的共识似乎是这样

  • 在这里使用goto是没有必要的 - while循环可以做得很好.
  • 使用这样的例外并不是一个好主意 - 虽然我不知道该替换它.

Jos*_*osh 15

当你想在处理异常后重试操作时,人们通常会从这样的错误中恢复吗?

是的,在调用代码中.让这个方法的调用者决定是否需要重试逻辑.

更新:

澄清一下,如果你能真正处理它们,你应该只捕获异常.你的代码基本上说:

"我不知道发生了什么事,但无论我做了什么都会导致一切都爆炸......所以让我们再做一次."

捕获可以从中恢复的特定错误,并让其余的泡沫到达要处理的下一层.任何使它一直到顶部的异常代表了那时的真正错误.

更新2:

好吧,所以不要通过评论继续进行相当冗长的讨论,我将用半伪代码示例详细说明.

一般的想法是,您只需重新构建代码以执行测试,并更好地处理用户体验.

//The main thread might look something like this

try{
    var database = LoadDatabaseFromUserInput();

    //Do other stuff with database
}
catch(Exception ex){
    //Since this is probably the highest layer,
    // then we have no clue what just happened
    Logger.Critical(ex);
    DisplayTheIHaveNoIdeaWhatJustHappenedAndAmGoingToCrashNowMessageToTheUser(ex);
}

//And here is the implementation

public IDatabase LoadDatabaseFromUserInput(){

    IDatabase database = null;
    userHasGivenUpAndQuit = false;

    //Do looping close to the control (in this case the user)
    do{
        try{
            //Wait for user input
            GetUserInput();

            //Check user input for validity
            CheckConfigFile();
            CheckDatabaseConnection();

            //This line shouldn't fail, but if it does we are
            // going to let it bubble up to the next layer because
            // we don't know what just happened
            database = LoadDatabaseFromSettings();
        }
        catch(ConfigFileException ex){
            Logger.Warning(ex);
            DisplayUserFriendlyMessage(ex);
        }
        catch(CouldNotConnectToDatabaseException ex){
            Logger.Warning(ex);
            DisplayUserFriendlyMessage(ex);
        }
        finally{
            //Clean up any resources here
        }
    }while(database != null); 
}
Run Code Online (Sandbox Code Playgroud)

现在显然我不知道你的应用程序正在尝试做什么,这肯定不是一个生产示例.希望你能得到一般的想法.重构程序,以避免任何不必要的应用程序流中断.

干杯,乔希


Ara*_*and 7

也许我错过了一些东西,但为什么你不能使用while循环?如果您的代码提供了异常(这是一个错误的代码)功能,这将永远为您提供相同的循环.

IDatabase database = null;

while(database == null){
   try
   {
        database = databaseLoader.LoadDatabase();
   }
   catch(Exception e)
   {
        var connector = _userInteractor.GetDatabaseConnector();
        if(connector == null)
                throw new ConfigException("Could not load the database specified in your config file.");
        databaseLoader = DatabaseLoaderFacade.GetDatabaseLoader(connector);
        //just in case??
        database = null;
   }
 }
Run Code Online (Sandbox Code Playgroud)

如果你必须在普通代码中使用goto,那么你就错过了逻辑流程.你可以使用标准结构,if,while,等等.