Enum Overuse? - PullRequest
       33

Enum Overuse?

2 голосов
/ 09 июня 2009

Я не уверен, что злоупотребляю Enums здесь. Возможно, это не лучший подход к дизайну.

У меня есть enum, который объявляет возможные параметры для метода, который выполняет командные файлы.

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<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 ]

8 голосов
/ 09 июня 2009

Я бы, вероятно, пошел за дизайн по этим направлениям:

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 базовый класс

4 голосов
/ 09 июня 2009

Что если вам вдруг понадобится третий пакетный файл? Вы должны изменить свой код, перекомпилировать свою библиотеку, и все, кто ее использует, должны сделать то же самое.

Всякий раз, когда я нахожу, что пишу магические строки, которые могут измениться, я думаю поместить их в дополнительный файл конфигурации, не допуская данных в коде.

3 голосов
/ 09 июня 2009

Если вы хотите использовать enum, то вы можете рассмотреть возможность использования атрибутов, чтобы вы могли хранить дополнительную информацию (например, имя файла) для элементов.

Вот пример кода, демонстрирующий, как объявлять атрибуты:

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);
3 голосов
/ 09 июня 2009

Я бы лично использовал статический класс констант в этом случае:

public static class BatchFiles
 { 
   public const string batch1 = "batch1.bat";
   public const string batch2 = "batch2.bat"; 
 }
2 голосов
/ 09 июня 2009

Я думаю, что последний подход лучше, потому что он разделяет проблемы. У вас есть метод, который предназначен для связывания значений перечисления с физическим путем, и отдельный метод для фактического выполнения результата. Первая попытка слегка смешала эти два подхода.

Однако я думаю, что использование оператора switch для получения пути также является правильным подходом. Перечисления во многих отношениях предназначены для включения.

1 голос
/ 09 июня 2009

Использование перечислений нормально, если вам не нужно добавлять новые пакетные файлы без перекомпиляции / повторного развертывания приложения ... однако я думаю, что наиболее гибкий подход - это определить список пар ключ / имя файла в вашей конфигурации.

Чтобы добавить новый пакетный файл, вы просто добавляете его в файл конфигурации / перезапускаете / говорите своему пользователю ключ. Вам просто нужно обработать неизвестный ключ / файл, не найденные исключения.

0 голосов
/ 09 июня 2009

Первое решение (переключатель) простое и прямолинейное, и вам действительно не нужно усложнять его.

Альтернативой использованию enum может быть использование свойств, которые возвращают экземпляры класса с соответствующим набором данных. Это довольно расширяемый; если позже вам понадобится метод 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();
0 голосов
/ 09 июня 2009

Второй подход лучше, потому что он связывает объекты пакетного файла (перечисления) со строками.

Но если говорить о дизайне, было бы не очень хорошо разделить перечисление и словарь; Вы можете рассмотреть это как альтернативу:

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.

0 голосов
/ 09 июня 2009

Проблема с последним случаем заключается в том, что что-то передало недопустимое значение, которого нет в словаре. Значение по умолчанию внутри оператора switch обеспечивает простой выход.

Но ... если вы enum, у вас будет много записей. Словарь может быть лучшим способом.

В любом случае, я бы порекомендовал какой-нибудь способ обеспечить защиту входного значения от неправильной ошибки даже в ответе ammoQ.

0 голосов
/ 09 июня 2009

Действительно ли необходимо, чтобы ExecuteBatch работал только с ограниченным числом возможных имен файлов? Почему бы тебе просто не сделать это

public void ExecuteBatch(string batchFile)
{
    ExecuteBatchFile(batchFile);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...