【问题标题】:Which operator is faster: ?: or &&哪个运算符更快:?: 或 &&
【发布时间】:2011-04-01 16:14:11
【问题描述】:

在开发 ASP.NET 应用程序时,我经常需要解析以字符串形式给出的布尔值,例如来自像?visible=true这样的查询字符串

我找到了两种实现解析的解决方案:

bool Visible
{
    get
    {
        bool b;
        return Boolean.TryParse(this.Request["visible"], out b) && b;
    }
}

bool Visible
{
    get
    {
        bool b;
        return Boolean.TryParse(this.Request["visible"], out b) ? b : false;
    }
}

您认为哪种方式更受欢迎?而且可能更快?

附:不是微选,我只是想了解一下

附言我对IL不熟悉所以决定在这里问

【问题讨论】:

  • @Yves:我对 IL 不熟悉,所以决定在这里询问

标签: c# asp.net .net boolean conditional-operator


【解决方案1】:

不要微优化,让它可读。

我认为这更具可读性:

bool visible;
Boolean.TryParse(this.Request["visible"], out visible);
return visible;

可读的变量名通常会有所帮助;)与其他两个相比,这种实现实际上产生的操作码更少,而且我认为它会在更少的周期内执行,比你的两次尝试都快。

因此,它不仅在 imo 上更具可读性,而且由于跳过了 if 语句,因此速度也更快。另外两个有相同的操作码,只是在检查时切换了逻辑。

[编辑 - 使用发布标志编译 - 更短的 IL]

如果你看下面三个实现:

public bool Visible1
{
    get 
    {
        bool b;
        return Boolean.TryParse(HttpContext.Current.Request["visible"], out b) && b;
    }
}

public bool Visible2
{
    get
    {
        bool b;
        return Boolean.TryParse(HttpContext.Current.Request["visible"], out b) ? b : false;
    }
}

public bool Visible3
{
    get
    {
        bool b;
        Boolean.TryParse(HttpContext.Current.Request["visible"], out b);
        return b;
    }
}

将产生以下 IL 代码:

.method public hidebysig specialname instance bool get_Visible1() cil managed
{
    .maxstack 2
    .locals init (
    [0] bool b)
    L_0000: call class [System.Web]System.Web.HttpContext [System.Web]System.Web.HttpContext::get_Current()
    L_0005: callvirt instance class [System.Web]System.Web.HttpRequest [System.Web]System.Web.HttpContext::get_Request()
    L_000a: ldstr "visible"
    L_000f: callvirt instance string [System.Web]System.Web.HttpRequest::get_Item(string)
    L_0014: ldloca.s b
    L_0016: call bool [mscorlib]System.Boolean::TryParse(string, bool&)
    L_001b: brfalse.s L_001f
    L_001d: ldloc.0 
    L_001e: ret 
    L_001f: ldc.i4.0 
    L_0020: ret 
}

.method public hidebysig specialname instance bool get_Visible2() cil managed
{
    .maxstack 2
    .locals init (
    [0] bool b)
    L_0000: call class [System.Web]System.Web.HttpContext [System.Web]System.Web.HttpContext::get_Current()
    L_0005: callvirt instance class [System.Web]System.Web.HttpRequest [System.Web]System.Web.HttpContext::get_Request()
    L_000a: ldstr "visible"
    L_000f: callvirt instance string [System.Web]System.Web.HttpRequest::get_Item(string)
    L_0014: ldloca.s b
    L_0016: call bool [mscorlib]System.Boolean::TryParse(string, bool&)
    L_001b: brtrue.s L_001f
    L_001d: ldc.i4.0 
    L_001e: ret 
    L_001f: ldloc.0 
    L_0020: ret 
}

.method public hidebysig specialname instance bool get_Visible3() cil managed
{
    .maxstack 2
    .locals init (
    [0] bool b)
    L_0000: call class [System.Web]System.Web.HttpContext [System.Web]System.Web.HttpContext::get_Current()
    L_0005: callvirt instance class [System.Web]System.Web.HttpRequest [System.Web]System.Web.HttpContext::get_Request()
    L_000a: ldstr "visible"
    L_000f: callvirt instance string [System.Web]System.Web.HttpRequest::get_Item(string)
    L_0014: ldloca.s b
    L_0016: call bool [mscorlib]System.Boolean::TryParse(string, bool&)
    L_001b: pop 
    L_001c: ldloc.0 
    L_001d: ret 
}

【讨论】:

  • 不是微选,我只是想了解一下
  • @abatishchev:用正确的 IL 代码编辑了我的答案。前一个是调试版本,没有优化。结果我提出的代码也更快。主要是因为跳过了 if 语句。
【解决方案2】:

与页面生命周期的成本相比,它们两者之间的速度差异将是无限小的。它们的主要问题是它们的可读性不强。您为什么不简单地执行以下操作:

return Request["visible"] == "true";

它达到了同样的目的,而且非常清楚。我看不出您所做的任何事情的价值,这只是令人困惑。

【讨论】:

  • String.Equals(Request["visible"], Boolean.TrueString, StringComparison,OrdianlIgnoreCase) 可能更正确
  • "True".Equals(value, StringComparison.OrdinalIgnoreCase)) 是 TryParse 实际所做的。然后是“False。然后它会修剪空白,并在必要时再次检查两个字符串。
【解决方案3】:

其实不然

bool Visible
{
    get
    {
        bool b;
        Boolean.TryParse(this.Request["visible"], out b)
        return b;
    }
}

因为如果 TryParse 失败,b 将设置为 default(bool) (false)。

并且b 必须由 TryParse 设置,因为它是一个 out 变量。

不要进行微优化,编写可读性强的代码。

【讨论】:

    【解决方案4】:

    在这种情况下,它根本不会产生任何显着差异。解析字符串需要更长的时间,以至于运算符之间的微小差异无关紧要。

    如果它会产生任何影响,您应该分析代码以了解哪个实际上更快。真正的性能不仅取决于单个运算符,还取决于代码中该点之前和之后进行了哪些操作。

    有根据的猜测是&& 运算符要快一些。因为没有条件跳转,所以它更适合现代处理器所做的连续操作的并行处理。

    【讨论】:

      【解决方案5】:

      我认为它们在功能上可能都错了(也许我不明白你在做什么),但即使它们是正确的,你也不在乎哪个更快。

      你真的,真的不在乎。

      【讨论】:

      • 我只是想知道,可能在 IL 级别
      • @abatishchev:然后看看 IL。
      【解决方案6】:

      第一个更好一些,因为它使用的代码更少,所以我会选择它。

      我怀疑两者之间的速度差异很大,但如果你真的关心你应该对它们进行分析 - 每个运行一百万次左右并记录运行时间。

      【讨论】:

      • 或查看它们生成的 IL。无论哪种情况,这都是微优化,没关系。按照您的建议,使用干净的代码。
      猜你喜欢
      • 2012-07-30
      • 2011-06-10
      • 1970-01-01
      • 1970-01-01
      • 2016-03-20
      • 2019-11-13
      • 2011-03-08
      • 1970-01-01
      • 2014-11-04
      相关资源
      最近更新 更多