C# If语句:在相同条件下处理分层的最佳方法

C# If语句:在相同条件下处理分层的最佳方法,c#,if-statement,C#,If Statement,我对编程相当陌生,但我一直在努力确保我学到了良好的设计实践。我的问题是关于如何处理这种if语句的情况,因为它似乎违反了不要重复你自己 我有一个带有构造函数的类,它包含一个连接到数据库的方法。如果连接代码块中存在错误,该方法将写入字符串。然后,我有一个process方法来分析数据库的元数据,如果发现任何错误,也会写入错误。如果连接方法中已经存在错误,我不希望运行元数据分析,但这是最好的方法吗 public bool Process() { if (ErrorLog == null)

我对编程相当陌生,但我一直在努力确保我学到了良好的设计实践。我的问题是关于如何处理这种
if语句
的情况,因为它似乎违反了
不要重复你自己

我有一个带有构造函数的类,它包含一个连接到数据库的方法。如果连接代码块中存在错误,该方法将写入
字符串。然后,我有一个process方法来分析数据库的元数据,如果发现任何错误,也会写入错误。如果连接方法中已经存在错误,我不希望运行元数据分析,但这是最好的方法吗

public bool Process()
{
    if (ErrorLog == null)
    {
        //Metadata analysis code that may write errors

        if (ErrorLog == null)
            return true;
        else
            PublishErrorLog();
        return false;
    } 
    else
        PublishErrorLog();
    return false;
}

最后一个函数可能看起来很简单,如下所示:

public bool Process()
{
    if (hasError())
        return false;
    //Metadata analysis code that may write errors
    //Note that error log may change here
    return !hasError(); //updated by juharr
}
说明:

如果带有
//metadata analysis
的行实际上可以更改
ErrorLog
的状态,则您显示的代码可能与此情况不完全相同

简化步骤1:单个If-Else循环

但是,如果看到嵌套循环,我宁愿通过这样做使代码更易于处理和阅读

public bool Process()
{
    if (ErrorLog != null){
        PublishErrorLog();
        return false;
    }
        //Metadata analysis code that may write errors
       //Note that error log may change here

    if (ErrorLog != null){
        PublishErrorLog();
        return false;
    }

    return true;
}
bool hasError(){
    if (ErrorLog != null){
        PublishErrorLog();
        return true;
    }
    return false; //no error, can continue
}
基本上,与嵌套if-else相比,您可以先返回简单语句。如果满意,则返回,否则继续

这样,您的代码就变成了单个条件循环-没有嵌套循环

简化步骤2:错误日志+具有错误组合功能

您还可以进一步改进上面的代码,因为您的错误日志记录模式是相同的,您可以创建如下函数

public bool Process()
{
    if (ErrorLog != null){
        PublishErrorLog();
        return false;
    }
        //Metadata analysis code that may write errors
       //Note that error log may change here

    if (ErrorLog != null){
        PublishErrorLog();
        return false;
    }

    return true;
}
bool hasError(){
    if (ErrorLog != null){
        PublishErrorLog();
        return true;
    }
    return false; //no error, can continue
}
最终代码

然后,
进程
函数如下所示

public bool Process()
{
    if (hasError())
        return false;
    //Metadata analysis code that may write errors
    //Note that error log may change here
    return !hasError(); //updated by juharr
}

非常简洁。您也可以在其他地方重复该模式。

您的最终函数可能看起来很简单,如下所示:

public bool Process()
{
    if (hasError())
        return false;
    //Metadata analysis code that may write errors
    //Note that error log may change here
    return !hasError(); //updated by juharr
}
说明:

如果带有
//metadata analysis
的行实际上可以更改
ErrorLog
的状态,则您显示的代码可能与此情况不完全相同

简化步骤1:单个If-Else循环

但是,如果看到嵌套循环,我宁愿通过这样做使代码更易于处理和阅读

public bool Process()
{
    if (ErrorLog != null){
        PublishErrorLog();
        return false;
    }
        //Metadata analysis code that may write errors
       //Note that error log may change here

    if (ErrorLog != null){
        PublishErrorLog();
        return false;
    }

    return true;
}
bool hasError(){
    if (ErrorLog != null){
        PublishErrorLog();
        return true;
    }
    return false; //no error, can continue
}
基本上,与嵌套if-else相比,您可以先返回简单语句。如果满意,则返回,否则继续

这样,您的代码就变成了单个条件循环-没有嵌套循环

简化步骤2:错误日志+具有错误组合功能

您还可以进一步改进上面的代码,因为您的错误日志记录模式是相同的,您可以创建如下函数

public bool Process()
{
    if (ErrorLog != null){
        PublishErrorLog();
        return false;
    }
        //Metadata analysis code that may write errors
       //Note that error log may change here

    if (ErrorLog != null){
        PublishErrorLog();
        return false;
    }

    return true;
}
bool hasError(){
    if (ErrorLog != null){
        PublishErrorLog();
        return true;
    }
    return false; //no error, can continue
}
最终代码

然后,
进程
函数如下所示

public bool Process()
{
    if (hasError())
        return false;
    //Metadata analysis code that may write errors
    //Note that error log may change here
    return !hasError(); //updated by juharr
}

非常简洁。你也可以在其他地方重复这个模式。

其他答案都是有效的。但在我看来,这似乎是使用
异常的完美案例。无论何时,只要您写入
ErrorLog
,都会引发异常。然后,您可以在顶部正好有一个块来处理错误

public bool Process()
{
    if (ErrorLog != null)
        //At this point, the PublishErrorLog should have already been called.
        return false;

    try
    {
        // Do Metadata analysis that may throw errors
    }
    catch (ErrorLogException e)
    {
        PublishErrorLog()
        return false;
    }
    return true;
}
这样做的好处是元数据分析可以根据需要进行复杂和嵌套。它只需要抛出异常

编辑:

正如Aron所指出的,这可以在没有类成员的情况下完成。日志信息可以存储在异常本身中。捕捉块可能看起来像:

catch (ErrorLogException e)
{
    var logMessage = e.logMessage;
    PublishErrorLog(logMessage);
    return false;
}

其他答案都是正确的。但在我看来,这似乎是使用
异常的完美案例。无论何时,只要您写入
ErrorLog
,都会引发异常。然后,您可以在顶部正好有一个块来处理错误

public bool Process()
{
    if (ErrorLog != null)
        //At this point, the PublishErrorLog should have already been called.
        return false;

    try
    {
        // Do Metadata analysis that may throw errors
    }
    catch (ErrorLogException e)
    {
        PublishErrorLog()
        return false;
    }
    return true;
}
这样做的好处是元数据分析可以根据需要进行复杂和嵌套。它只需要抛出异常

编辑:

正如Aron所指出的,这可以在没有类成员的情况下完成。日志信息可以存储在异常本身中。捕捉块可能看起来像:

catch (ErrorLogException e)
{
    var logMessage = e.logMessage;
    PublishErrorLog(logMessage);
    return false;
}

您似乎正在使用
ErrorLog
属性来表示连接的有效性。如果
ErrorLog
是一个字符串,正如我从您的问题中了解到的那样,我将有一种特定的方法来判断连接是否有效,并且不依赖于日志的空值

e、 g


您似乎正在使用
ErrorLog
属性来表示连接的有效性。如果
ErrorLog
是一个字符串,正如我从您的问题中了解到的那样,我将有一种特定的方法来判断连接是否有效,并且不依赖于日志的空值

e、 g


只捕获“内部”的异常(捕获(MetadataException){}),然后捕获“外部”的其他异常如何?我建议您在任何if语句中始终使用“{”和“}”,即使这只是一条单行线。请注意,您呈现的条件并不完全相同,因为您提到所有
//元数据分析
过程都会更改
错误日志
。对我来说,这里的要点是将错误处理部分隔离。看看我的答案。这样,您可以很容易地集中处理错误部分。如果希望
ErrorLog
不存在,您还可以为它生成进一步的函数。您所说的是一个包含错误的对象,以及在创建其中一个错误时跳出代码的控制流。在C#中,我们称这些
Exception
s,它们不应该存储在字段中。它们应该被捕获。我投票将这个问题作为主题外的问题来结束,因为这段代码显然属于CodeReview,因为代码的行为符合设计。只捕获“内部”的异常(catch(MetadataException){}),然后捕获“外部”的其他异常如何?我建议你在任何if语句中都使用“{”和“}”