【问题标题】:Convert ?: statement to handle more than 2 answers转换 ?: 处理超过 2 个答案的语句
【发布时间】:2012-08-31 19:30:19
【问题描述】:

我对编程还很陌生,但我的任务是维护一些由以前的员工创建的应用程序。我有一个 ?: 声明,现在需要处理的不仅仅是真假声明,但我不知道如何去做。有问题的代码是:

    MailDomainContext mail = new MailDomainContext();
      mail.Load(mail.GetMailsQuery("Workforce Attendence Issue",
               loadEmp.Entities.Where(emp => emp.EmployeeID == _EmployeeID).First().Username,
               (loadEmp.Entities.Where(emp => emp.EmployeeID == _EmployeeID).First().EmployeeShiftID >= 2 ? "supervisor1" : "supervisor2"),
               loadEmp.Entities.Where(emp => emp.EmployeeID == _EmployeeID).First().FirstName,
               attendence.AttendenceDate.ToString("MM/dd/yyyy"),
               attendence.TimeLost,
               loadAbs.Entities.Where(abs => abs.AbsenceID == attendence.AbsenceID).First().AbsenceDescription,
               (from inf in loadAtt.Entities
               where inf.EmployeeID == _EmployeeID
               where inf.AttendenceDate > DateTime.Now.AddDays(30 * -1)
               where inf.Approved == false
               select inf).Count() + 1,
               attendence.UTOUsed
               ), null, null);

更具体地说,这一行:

    (loadEmp.Entities.Where(emp => emp.EmployeeID == _EmployeeID).First().EmployeeShiftID >= 2 ? "supervisor1" : "supervisor2"),

我需要在列表中再添加 4 位主管,但我还没有想出一个不会让其他所有事情都不满意的方法。如果这是一个过于简单的问题,或者我遗漏了一些您可能需要知道的细节,我深表歉意,因为我说过我对这一切都很陌生。

【问题讨论】:

  • 是否是sup1-sup6的标准是什么?
  • 让您的代码更具可读性将是一个好的开始。我会将loadEmp.Entities.Where(emp => emp.EmployeeID == _EmployeeID).First() 放入一个变量中,而不是一遍又一遍地调用它。
  • 主管取决于 ShiftID 是什么。
  • 我认为这是一个人为了自己的利益而变得有点太聪明的例子,代码不应该看起来像这样。

标签: c# linq


【解决方案1】:

此代码不必要地难以维护,而且效率低下且防御性不强。该代码正在检索员工 3 次。

loadEmp.Entities.Where(emp => emp.EmployeeID == _EmployeeID).First().Username

如果_EmployeeID 的员工不存在,上述行(和其他行)将引发异常。相反,您可以使用 FirstOrDefaultSingleOrDefault 如果您希望只有一名员工具有该 ID(应该是这种情况,因为它看起来像该实体的主键)。如果loadEmp 实际上是一个实体框架DbContext,那么你也可以使用Find

您可以执行一次此查询并将结果存储在局部变量中。

var employee = loadEmp.Entities.SingleOrDefault(emp => emp.EmployeeID == _EmployeeID);

if (employee == null)
{
   // Handle employee not found
}

然后要根据员工获取主管字符串,您可以创建一个方法,该方法采用计算主管字符串所需的最少信息量,并将其传递给方法以获取结果。

GetSupervisorRole(employee.EmployeeShiftID);

...

private string GetSupervisorRole(int employeeShiftID)
{
   // Logic here
}

【讨论】:

  • 你是唯一真正建议作者修复他可怕的代码的人。
【解决方案2】:

一种方法是将该代码提取到一个方法中,然后以任何您想要的方式编写该方法。

另一种方法是使用字典将键(如果它们的数量很少)映射到值。

var id =3;
var mapping = new Dictionary<int, string>() { 
  { 1, "first" },
  { 2, "second" },
  { 3, "first" } //you can map 2 values (1,3) to the same "first" string
};

string value;
if (!mapping.TryGetValue(id, out value))
{
  value = "unknown";
}

【讨论】:

    【解决方案3】:

    创建以下方法:

    string GetSupervisor(int employeeShiftId) {
        if (employeeShiftId == 1) supervisor = "supervisor1";
        else if (employeeShiftId == 2) supervisor = "supervisor2";
        else if (employeeShiftId == 3) supervisor = "supervisor3";
        else if (employeeShiftId == 4) supervisor = "supervisor4";
    }
    

    然后从您的代码中调用它并将结果分配给变量supervisor,然后您可以在mail.Load() 中使用它:

    int employeeShiftId = loadEmp.Entities
              .Where(emp => emp.EmployeeID == _EmployeeID).First()
              .EmployeeShiftID;
    string supervisor = GetSupervisor(employeeShiftId);
    
    MailDomainContext mail = new MailDomainContext();
    mail.Load(mail.GetMailsQuery("Workforce Attendence Issue",
                   loadEmp.Entities.Where(emp => emp.EmployeeID == _EmployeeID).First().Username,
                   supervisor, // <-- Then use it here
                   ...
    );
    

    【讨论】:

      【解决方案4】:

      我会替换整个部分

      loadEmp.Entities.Where(emp => emp.EmployeeID == _EmployeeID).First().Username,
      (loadEmp.Entities.Where(emp => emp.EmployeeID == _EmployeeID).First().EmployeeShiftID >= 2 ? "supervisor1" : "supervisor2"),
       loadEmp.Entities.Where(emp => emp.EmployeeID == _EmployeeID).First().FirstName,
      

      //Assign these variables ahead of time so others reading your code can 
      //figure out what's going on
      var EmpID = loadEmp.Entities.Where(emp => emp.EmployeeID == _EmployeeID).First();
      var UserName = EmpID.UserName;
      var FirstName = EmpID.FirstName;
      var Title = GetTitle(EmpID.EmployeeShiftID);
      
      //Your original call
      Mail.Load(mail.GetMailsQuery("Workforce Attendence Issue",
           UserName,
           Title,
           FirstName,
           //...Etc
      );
      
      //New method you will need to add, you could do this logic in line, but this will
      //be less messy
      private string GetTitle(int ShiftID)
      {
          switch (ShiftID)
          {
               case 1:
                   return "supervisor1";
                   break;
               case 2:
                   return "supervisor2";
                   break;
               //...etc
          }
      }
      

      【讨论】:

        【解决方案5】:

        这并不是一个好主意,但您可以像这样组合内联:

            static void Main(string[] args)
            {
                int EmpId = 2;
                string supervisor = EmpId == 4 ? "Supervisor4" :
                                    EmpId == 3 ? "Supervisor3" :
                                    EmpId == 2 ? "supervisor2" :
                                                 "supervisor1" ;
                Console.WriteLine(supervisor);
        
            }
        

        您可以在另一个堆栈问题中看到另一个示例:Legible or not: C# multiple ternary operators + Throw if unmatched

        我可能会改用 KDiTraglia 建议的方法方法,您只需传入 EmpId 并取回主管名称,或者像 Alexei Levenkov 建议的字典查找方法。

        【讨论】:

        • @BlueM - 我认为这是一段可怕的代码,即使作者也这么认为。这解决了问题作者的问题,但总体而言这是一个可怕的想法。
        猜你喜欢
        • 1970-01-01
        • 2015-11-16
        • 2014-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-29
        相关资源
        最近更新 更多