C#重构if-else语句代码

dot*_*ner 5 c# refactoring

请查看我的以下代码......

public enum LogType
{
    Debug,
    Info,
    Warn,
    Error,
    Fatal
}

private static readonly ILog log = 
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

public void LogError(LogType logtype, string message)
{
    XmlConfigurator.Configure();
    if (logtype == LogType.Debug)
        log.Debug(message);
    else if (logtype == LogType.Error)
        log.Error(message);
}
Run Code Online (Sandbox Code Playgroud)

我不喜欢上面所有的if-else语句,并且相信有更简洁的方法来编写它.我怎么能重构它?log类有不同的Debug,Error等方法.

我想单独调用一个方法让它自动处理它.

LogMyError(LogType.Debug, "I am just logging here");
Run Code Online (Sandbox Code Playgroud)

我该怎么办?我宁愿远离switch语句.我正在寻找一种干净的面向对象的方法.

Eri*_*ert 16

你的代码完全没问题; 我不会改变它.

然而,这是有益的思考如何这样做,如果你想更"面向对象"了.我们只考虑你的两个案例; 其他人可以很容易地看到它们将如何实施:

public abstract class LogType
{
    public static readonly LogType Debug = new LogTypeDebug();
    public static readonly LogType Error = new LogTypeError();

    private LogType() {} // Prevent anyone else from making one.

    public abstract void LogMessage(ILog logger, string message);

    private sealed class LogTypeDebug: LogType
    {
        public override void LogMessage(ILog logger, string message)
        {
            logger.Debug(message);
        }
    }

    private sealed class LogTypeError: LogType
    {
        public override void LogMessage(ILog logger, string message)
        {
            logger.Error(message);
        }
    }
}
...

//Obtain the log object the way you prefer.
private static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

public void LogError(LogType logtype, string message)
{
    logtype.LogMessage(log, message);
}
Run Code Online (Sandbox Code Playgroud)

呼叫站点根本没有变化!它仍然看起来像:

LogError(LogType.Debug, "my message");
Run Code Online (Sandbox Code Playgroud)

在那里你去:没有ifswitch声明!"打开类型"代码已被移动到虚拟功能表中,该位于面向对象的代码中.

这种技术的一个很好的副作用是你永远不必担心有人将一个整数转换为枚举类型的不受支持的值.LogType类型的变量的唯一可能值为null或对其中一个单例的引用.

  • @ dotnet-practitioner:这与问题有关吗?我在这里没有关注你的思路.答案的要点是向您展示如何以面向对象的方式完成此任务; 在某种程度上还不清楚吗? (2认同)

Ode*_*ded 11

您可以使用a Dictionary<LogType,Action<string>>来保存要为每个枚举值执行的操作,然后只需调用委托.

var logActions = new Dictionary<LogType,Action<string>>();
logActions.Add(LogType.Debug, log.Debug);
...

logActions[logtype](message);
Run Code Online (Sandbox Code Playgroud)

更新:

如果您的if陈述中只有少量分支,那就太过分了.我会将此方法用于5个以上的ifs.

  • @ dotnet-practitioner - 看一下Eric Lippert的[答案](http://stackoverflow.com/a/10036020/1583),其中使用了一种继承方法(如果你有几种不同的方法,这是一种更好的方法致电). (2认同)

Tig*_*ran 5

Imo,没有任何明显的理由来改变代码中的任何内容.功能清晰,if/else定义清晰.函数声明允许您以您想要的方式使用它.

所以我不会改变我看到的代码中的任何内容.

祝好运.