【问题标题】:Nested ternary operators嵌套三元运算符
【发布时间】:2011-10-29 13:25:01
【问题描述】:

我有这个代码:

_viewModel.PhoneDefault = user == null ? "" :
    (string.IsNullOrEmpty(user.PhoneDay) ?
        (string.IsNullOrEmpty(user.PhoneEvening) ?
            (string.IsNullOrEmpty(user.Mobile) ? "" : 
                user.Mobile) :
            user.PhoneEvening) :
         user.PhoneDay);

有没有更好的方法来编写它以使其更具可读性?

【问题讨论】:

  • 避免嵌套三元组肯定会让代码更具可读性
  • 你考虑过使用“switch”吗?

标签: c# refactoring ternary-operator


【解决方案1】:

只是回答,因为我在任何现有答案中都没有看到我在这种情况下使用的方法。

怎么样……

_viewModel.PhoneDefault = user == null ? string.Empty :
    !string.IsNullOrEmpty(user.PhoneDay)     ? user.PhoneDay :
    !string.IsNullOrEmpty(user.PhoneEvening) ? user.PhoneEvening :
    !string.IsNullOrEmpty(user.Mobile)       ? user.Mobile : 
    string.Empty;

您必须在一开始就检查用户是否为空,这很不方便,因为这会强制重复string.Empty,但我认为它的可读性很好。

我的两分钱;)

【讨论】:

  • 除了可读性之外,嵌套三元组的另一件事是可维护性 - 逻辑中的任何细微变化都可能使您将其分解为简单的条件 - 否则您必须继续扩大单个语句。嵌套三元组可能看起来很酷,但在团队合作中可能不值得酷——这就是我的想法。如果团队很小并且所有人都在使用上达成一致,或者只有一个人可能没有区别:)
【解决方案2】:

现在,借助 LINQ 的强大功能,您可以在单行中使其简单易读,就像

_viewModel.PhoneDefault = user == null ? "" :
(new [] {user.PhoneDay, user.PhoneEvening, user.Mobile}).FirstOrDefault(s => !string.IsNullOrEmpty(s)) ?? "";

【讨论】:

    【解决方案3】:

    虽然我最喜欢 Gabe 和 Vladimir 的回答。这是一种使嵌套三元组看起来可辨认的方法。

    _viewModel.PhoneDefault =
      user == null
        ? ""
      : (string.IsNullOrEmpty(user.PhoneDay)
        ? (string.IsNullOrEmpty(user.PhoneEvening)
          ? (string.IsNullOrEmpty(user.Mobile)
               ? ""
             : user.Mobile)
          : user.PhoneEvening)
        : user.PhoneDay);
    

    当然,因为您必须用括号将它们括起来,这使得执行此操作变得更加困难。在 JavaScript 中,它实际上非常优雅,因为它 允许没有括号的嵌套三元组。虽然您的情况并不真正需要这种语法,但有时这种语法会非常方便。

    【讨论】:

      【解决方案4】:

      编写一个单独的方法来获取电话号码,如下所示:

      public string GetDefaultPhone(User user)
              {
                  if(user == null)
                  {
                      return string.Empty;
                  }
      
                  if(!string.IsNullOrEmpty(user.PhoneDay))
                  {
                      return user.PhoneDay;
                  }
      
                  if(!string.IsNullOrEmpty(user.PhoneEvening))
                  {
                      return user.PhoneEvening;
                  }
      
                  if(!string.IsNullOrEmpty(user.Mobile))
                  {
                      return user.Mobile;
                  }
      
                  return string.Empty;
              }
      

      然后在你的代码中:

      _viewModel.PhoneDefault = GetDefaultPhone(user);
      

      【讨论】:

        【解决方案5】:

        好吧,只要条目可以为空或有效:

        if (user == null)
        {
            _viewModel.PhoneDefault = String.Empty;
        }
        else
        {
            _viewModel.PhoneDefault = user.PhoneDay ?? user.PhoneEvening ?? user.Mobile ?? String.Empty;
        }
        

        你甚至可以在字符串上定义一个扩展方法来将空字符串转换为null并在这里使用它,但我只是疯了。

        如果它们可以是空字符串,请使用其他人的答案。 Jason 的方法很干净。

        【讨论】:

          【解决方案6】:

          在您的情况下,您可以编写一个辅助函数,如下所示:

          // return the first parameter that isn't null or empty
          public static string CoalesceStrings(params string[] src)
          {
              foreach (var str in src)
                  if (!string.IsNullOrEmpty(str))
                      return str;
              return "";
          }
          

          然后直接调用它,像这样:

          _viewModel.PhoneDefault = user == null ? "" :
              CoalesceStrings(user.PhoneDay, user.PhoneEvening, user.Mobile);
          

          【讨论】:

            【解决方案7】:

            添加更多括号可能会使其更具可读性。您还可以将其分解为一系列 if/else 语句

            if (user != null)
            {
              if (!string.IsNullOrEmpty(user.PhoneDay))
                _viewModel.PhoneDefault = user.PhoneDay;
              else if (!string.IsNullOrEmpty(user.PhoneEvening))
                _viewModel.PhoneDefault = user.PhoneEvening;
              else if (!string.IsNullOrEmpty(user.Mobile))
                _viewModel.PhoneDefault = user.Mobile;
              else
                _viewModel.PhoneDefault = "";
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2020-10-06
              • 2014-10-02
              • 1970-01-01
              • 1970-01-01
              • 2013-11-07
              相关资源
              最近更新 更多