简体   繁体   中英

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

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

data.Task_Flag = boolean

User.TASKX = boolean

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.

Edit:

As everyone can now see, the real problem of refactoring this example lies in refactoring User.TASKX. Making it a list should suffice - as it could then be indexed by the same string 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...

Could you have an array/list of tasks instead and use Task_CallID as an index into that?

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
  2. Use reflection to find the property based on the number bit (X) and set that property

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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