Enum过度使用?

时间:2009-06-09 05:13:35

标签: c# dictionary enums

我不确定我是否在这里滥用枚举。也许这不是最好的设计方法。

我有一个枚举,它声明了执行批处理文件的方法的可能参数。

public enum BatchFile
{
    batch1,
    batch2
}

然后我有我的方法:

public void ExecuteBatch(BatchFile batchFile)
{
    string batchFileName;
    ...
    switch (batchFile)
        {
            case BatchFile.batch1:
                batchFileName = "Batch1.bat";
                break;
            case BatchFile.batch2:
                batchFileName = "Batch2.bat";
                break;
            default:
                break;
        }
    ...
    ExecuteBatchFile(batchFileName);
}

所以我想知道这是否是合理的设计。

我想到的另一个选择是创建一个Dictionary<>在这样的构造函数中:

Dictionary<BatchFile, String> batchFileName = new Dictionary<BatchFile, string>();
batchFileName.Add(BatchFile.batch1, "batch1.bat");
batchFileName.Add(BatchFile.batch2, "batch2.bat");

然后我不会使用switch语句而是:

public void ExecuteBatch(BatchFile batchFile)
{
    ExecuteBatchFile(batchFileName[batchFile]);
}

我猜测后者是更好的方法。

10 个答案:

答案 0 :(得分:8)

我可能会按照以下方式进行设计:

public interface IBatchFile
{
    void Execute();
}

public class BatchFileType1 : IBatchFile
{
    private string _filename;

    public BatchFileType1(string filename)
    {
        _filename = filename;
    }

    ...

    public void Execute()
    {
        ...
    }
}

public class BatchFileType2 : IBatchFile
{
    private string _filename;

    public BatchFileType2(string filename)
    {
        _filename = filename;
    }

    ...

    public void Execute()
    {
        ...
    }
}

实际上,我会将任何常用功能提取到BatchFile基类

答案 1 :(得分:4)

如果您突然需要第三批文件怎么办?您必须修改代码,重新编译库以及使用它的每个人都必须这样做。

每当我发现自己编写可能会发生变化的魔术字符串时,我会考虑将它们放入一个额外的配置文件中,从而将数据保留在代码之外。

答案 2 :(得分:3)

在这种情况下,我个人会使用静态类常量:

public static class BatchFiles
 { 
   public const string batch1 = "batch1.bat";
   public const string batch2 = "batch2.bat"; 
 }

答案 3 :(得分:3)

如果您想使用枚举,那么您可能需要考虑使用属性,以便您可以针对元素存储额外的信息(例如文件名)。

以下是一些示例代码,用于演示如何声明属性:

using System;

public enum BatchFile
{
    [BatchFile("Batch1.bat")]
    batch1,
    [BatchFile("Batch2.bat")]
    batch2
}

public class BatchFileAttribute : Attribute
{
    public string FileName;
    public BatchFileAttribute(string fileName) { FileName = fileName; }
}

public class Test
{
    public static string GetFileName(Enum enumConstant)
    {
        if (enumConstant == null)
            return string.Empty;

        System.Reflection.FieldInfo fi = enumConstant.GetType().GetField(enumConstant.ToString());
        BatchFileAttribute[] aattr = ((BatchFileAttribute[])(fi.GetCustomAttributes(typeof(BatchFileAttribute), false)));
        if (aattr.Length > 0)
            return aattr[0].FileName;
        else
            return enumConstant.ToString();
    }
}

要获取文件名,只需调用:

string fileName = Test.GetFileName(BatchFile.batch1);

答案 4 :(得分:2)

我认为后一种方法更好,因为它将问题分开了。您有一个专门用于将枚举值与物理路径相关联的方法以及用于实际执行结果的单独方法。第一次尝试略微混合了这两种方法。

但是我认为使用switch语句来获取路径也是一种有效的方法。枚举在很多方面都有待改变。

答案 5 :(得分:1)

如果您不需要在不重新编译/重新部署应用程序的情况下添加新批处理文件,那么使用枚举是可以的...但是我认为最灵活的方法是在配置中定义键/文件对对列表。

要添加新的批处理文件,只需将其添加到配置文件/ restart /告诉用户密钥。您只需要处理未找到的未知密钥/文件异常。

答案 6 :(得分:0)

ExecuteBatch是否真的只能在有限数量的可能文件名上工作? 你为什么不这样做?

public void ExecuteBatch(string batchFile)
{
    ExecuteBatchFile(batchFile);
}

答案 7 :(得分:0)

后一种情况的问题是,如果某些内容传递了一个不在字典内的无效值。 switch语句中的默认值提供了一个简单的方法。

但是......如果你的enum会有很多条目。字典可能是更好的方式。

无论哪种方式,我都建议使用某种方法来保护输入值,即使在ammoQ的答案中也不会导致错误。

答案 8 :(得分:0)

第二种方法更好,因为它将批处理文件对象(枚举)与字符串链接起来。

但是谈到设计,将枚举和字典分开是不太好的;您可以将此视为替代方案:

public class BatchFile {
    private batchFileName;

    private BatchFile(String filename) {
        this.batchFileName = filename;
    }
    public const static BatchFile batch1 = new BatchFile("file1");
    public const static BatchFile batch2 = new BatchFile("file2");

    public String getFileName() { return batchFileName; }
}

您可以选择将构造函数保密,也可以将其公开。

干杯,

JRH。

答案 9 :(得分:0)

第一个解决方案(交换机)简单直接,你真的不需要让它变得更复杂。

使用枚举的替代方法可以是使用返回具有相关数据集的类的实例的属性。这是非常可扩展的;如果你以后需要Execute方法对某些批处理方式有所不同,你可以让一个属性返回一个具有不同实现的子类,它仍然以相同的方式调用。

public class BatchFile {

   private string _fileName;

   private BatchFile(string fileName) {
      _fileName = fileName;
   }

   public BatchFile Batch1 { get { return new BatchFile("Batch1.bat"); } }
   public BatchFile Batch2 { get { return new BatchFile("Batch2.bat"); } }

   public virtual void Execute() {
      ExecuteBatchFile(_fileName);
   }

}

用法:

BatchFile.Batch1.Execute();