简体   繁体   English

重构我的C#代码 - 切换语句

[英]Refactor my C# code - Switch statement

I have the following code which I am are currently using .... Basically, this method assigns the correct boolean flag (TRUE/FALSE) for each Task. 我有以下代码,我目前正在使用....基本上,此方法为每个任务分配正确的布尔标志(TRUE / FALSE)。 As more and more tasks need to be added .. I can see that the switch statement will have to grow to cater for every task. 随着越来越多的任务需要添加..我可以看到switch语句必须增长以满足每个任务。

There has to be an easier way ... to keep the method small. 必须有一种更简单的方法......保持方法小。

Code: (forget naming convention, it has been changed for posting) 代码:(忘记命名约定,它已被更改为发布)

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 = String Representation of the Tasks ClassStructure.Tasks_CallIDs_Strings =字符串表示任务

data.Task_Flag = boolean data.Task_Flag =布尔值

User.TASKX = boolean User.TASKX =布尔值

Any feedback is welcome. 欢迎任何反馈。 I am sure there is an easy solution. 我相信有一个简单的解决方案。

For a lot of values like these, I would use a map something like this: 对于像这样的很多值,我会使用这样的地图:

Dictionary<ClassStructure.Tasks_CallIDs_Strings, Task_Flag>

and retrieve values by mapping the CallIDs strings. 并通过映射CallIDs字符串来检索值。

Edit: 编辑:

As everyone can now see, the real problem of refactoring this example lies in refactoring User.TASKX. 正如大家现在所看到的,重构这个例子的真正问题在于重构User.TASKX。 Making it a list should suffice - as it could then be indexed by the same string ClassStructure.Tasks_CallIDs_Strings 使它成为一个列表就足够了 - 因为它可以被相同的字符串ClassStructure索引.Tasks_CallIDs_Strings

Oh... Reconsider your naming scheme. 哦......重新考虑你的命名方案。

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);

I was thinking something like this - but maybe I missed the point of what it is all for? 我在想这样的事情 - 但也许我错过了这一切的重点?

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);
        }
    }
}

The Task class could have properties that allowed you to pass a function pointer (to the function that actually executes a task) if you needed that kind of flexibility - and you could add other methods like ExecuteTasks to User as well... 如果您需要这种灵活性,Task类可以具有允许您传递函数指针(到实际执行任务的函数)的属性 - 并且您可以向User添加其他方法,如ExecuteTasks ......

Could you have an array/list of tasks instead and use Task_CallID as an index into that? 你可以改为使用数组/任务列表,并使用Task_CallID作为索引吗?

eg 例如

User.Tasks[Task_CallID] = data.Task_Flag;

If you must have them all as members there are other options: 如果您必须将它们全部作为成员,还有其他选择:

  1. Maintain a mapping from Task_Call_ID to PropertyInfo reference and use that to set the correct property 保持从Task_Call_ID到PropertyInfo引用的映射,并使用它来设置正确的属性
  2. Use reflection to find the property based on the number bit (X) and set that property 使用反射根据数字位(X)查找属性并设置该属性

Both of these are reflection based and a bit nasty. 这两个都是基于反射的,有点讨厌。

Why not make a Users Tasks structured as a list: 为什么不将用户任务结构化为列表:

User Class 用户类

public List<ClassStructure.Tasks> Tasks {
    get; set;
}

Your Method becomes: 您的方法变为:

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

Which is to say that you don't need the method at all. 也就是说你完全不需要这个方法。 Your accessor then becomes running Find on a user's Tasks and checking the Tasks flag. 然后,您的访问者将运行查找用户的任务并检查任务标志。

Dictionary is a great alternative for this. 字典是一个很好的选择。 However, when a switch/case gets very complex look at using the strategy pattern (not for your scenario though). 但是,当交换机/案例变得非常复杂时,请考虑使用策略模式(尽管不适用于您的场景)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM