重构我的C#代码 - Switch语句

4
我有以下代码,目前正在使用...基本上,此方法为每个任务分配正确的布尔标志(TRUE/FALSE)。随着越来越多的任务需要添加...我可以看到,switch语句将不得不增长以适应每个任务。
必须有一种更简单的方法...使该方法保持小巧。
代码:(忘记命名约定,已更改发布)
public ClassStructure.User AssignTaskStatusToUser(ClassStructure.User,
                                                  List<ClassStructure.Tasks> TaskStatus)
{
    foreach (ClassStructure.Tasks data in TaskStatus)
    {
        string Task_CallID = data.Task_Call_ID;

        switch (Task_CallID)
        {
            case ClassStructure.Tasks_CallIDs_Strings.TASK1:
                User.TASK1 = data.Task_Flag;
                break;

            case ClassStructure.Tasks_CallIDs_Strings.TASK2:
                User.TASK2 = data.Task_Flag;
                break;

            case ClassStructure.Tasks_CallIDs_Strings.TASK3:
                User.TASK3 = data.Task_Flag;
                break;
        }
    }

    return User;
}

ClassStructure.Tasks_CallIDs_Strings = 任务的字符串表示

data.Task_Flag = 布尔值

User.TASKX = 布尔值

欢迎任何反馈。我相信有一个简单的解决方案。

6个回答

9

对于类似这样的许多值,我会使用以下类似的映射:

Dictionary<ClassStructure.Tasks_CallIDs_Strings, Task_Flag>

通过映射CallIDs字符串来检索值。

编辑:

正如每个人现在所看到的,重构此示例的真正问题在于重构User.TASKX。将其变为列表即可 - 因为它可以使用相同的字符串ClassStructure.Tasks_CallIDs_Strings进行索引。


+1,这也是我要建议的。 - Scott W
这是正确的...切换的原因是为了正确地分配User类的正确属性(Task)。 - James
除了使用字典之外,这个答案并不是很相关:它将Tasks_CallIDs_Strings映射到Task_Flag而不是用户属性分配。 - DK.
我认为User.TASKX需要重构,不如将其改为List。 - Elroy
我同意Elroy的观点。用户任务列表应该是一个列表。这样它就可以扩展到任意数量的任务。 - kpollock
显示剩余2条评论

2
哦...重新考虑你的命名方案。
public delegate void TaskAssigner(User user, bool taskFlag)

IDictionary<string, TaskAssigner> taskAssigners = new Dictionary<string, TaskAssigner>();

...

taskAssigners.Add(ClassStructure.Tasks_CallIDs_Strings.TASK1, (u, t) => u.TASK1 = t;);
taskAssigners.Add(ClassStructure.Tasks_CallIDs_Strings.TASK2, (u, t) => u.TASK2 = t;);

...

foreach(ClassStructure.Tasks data in TaskStatus)
    taskAssigners[data.Task_Call_ID](user, data.Task_Flag);

但这仍意味着我们必须为每个新任务添加一个“taskAssigners.Add…”行。我正在寻找一种无需维护的方法,即使随着时间的推移添加了额外的任务也能正常工作。 - James

2
我想,大概是这个意思吧——但也许我没理解它的全部含义?
public class User
{
    private Dictionary<string,Task> tasks;

    internal Dictionary<string,Task> Tasks
    {
      get { return tasks; }
      set { tasks = value; }
    }

    internal void AddTask(Task task)
    {
        tasks.Add(task.Task_Call_ID,task);
    }

    internal void AddTasks(List<Task> task)
    {
        foreach(Task task in Tasks)
        {
            tasks.Add(task.Task_Call_ID,task);
        }
    }
}

如果您需要这种灵活性,Task类可以具有允许您传递函数指针(指向实际执行任务的函数)的属性 - 您还可以像User一样添加其他方法,如ExecuteTasks...


1
您可以考虑使用一个任务的数组/列表,并使用Task_CallID作为索引吗?
例如:
User.Tasks[Task_CallID] = data.Task_Flag;

如果你必须将它们全部作为成员,还有其他选项:

  1. 维护一个从Task_Call_ID到PropertyInfo引用的映射,并使用它来设置正确的属性。
  2. 使用反射根据数字位(X)查找属性并设置该属性。

这两种方法都是基于反射的,有点棘手。


1
为什么不将用户任务构建为列表结构:
用户类
public List<ClassStructure.Tasks> Tasks {
    get; set;
}

你的方法变成了:

public void AssignTasks(User user, List<ClassStructure.Tasks> TaskStatus)    
{
    user.Tasks.AddRange(TaskStatus)   
}

也就是说,你根本不需要这个方法。 你的访问器现在变成了在用户的任务上运行查找并检查任务标志。


0

字典是一个很好的选择。然而,当 switch/case 变得非常复杂时,考虑使用策略模式(不适用于您的情况)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接