C#重构if-else语句代码

时间:2012-04-05 20:48:40

标签: 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);
}

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

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

LogMyError(LogType.Debug, "I am just logging here");

我怎么能做这样的事情?我宁愿远离switch语句。我正在寻找一种干净的面向对象的方法。

6 个答案:

答案 0 :(得分: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);
}

通话网站根本没有变化!它仍然看起来像:

LogError(LogType.Debug, "my message");

你去了:根本没有ifswitch陈述! “打开类型”代码已经移动到虚拟功能表中,这是它在面向对象代码中所属的位置。

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

答案 1 :(得分:11)

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

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

logActions[logtype](message);

更新

如果您的if语句中只有少量分支,那么这就太过分了。我会将此方法用于5个以上的ifs。

答案 2 :(得分:5)

Imo,没有任何明显的理由可以更改代码中的任何内容。 该功能很明确,并明确if/else定义。 函数声明允许您以想要使用它的方式使用它。

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

祝你好运。

答案 3 :(得分:3)

使用switch block

switch (logtype)
{
    case LogType.Debug:
        log.Debug(message);
        break;

    case LogType.Error:
        log.Error(message);
        break;

    //more cases here as needed...

    default:
        throw new InvalidArgumentException("logtype");
}

答案 4 :(得分:0)

始终有switch声明:

switch (logtype)
{
    case LogType.Debug:
        log.Debug(message);
        break;
    case LogType.Error:
        log.Error(message);
        break;
    ....
}

答案 5 :(得分:0)

您可以使用switch或使用LogType作为关键字创建字典,并使用相应的LogXXXX方法作为值 - Action<string>,然后执行< / p>

myDictionary[logType](message);