Какой оператор быстрее:?: Или && - PullRequest
4 голосов
/ 20 августа 2010

При разработке приложений 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;
    }
}

Как вы думаете, какой путь предпочтительнее? И, наверное, быстрее?

P.S. Это не микроопция, я просто хочу узнать

P.P.S. Я не знаком с ИЛ, поэтому решил спросить здесь

Ответы [ 6 ]

17 голосов
/ 20 августа 2010

Не оптимизируйте микро, сделайте его читабельным.

Я думаю, что это более читабельно:

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 
}
5 голосов
/ 20 августа 2010

Я думаю, что оба они, вероятно, неправильно функционируют (возможно, я не понимаю, что вы пытаетесь сделать), но даже если они верны, вам все равно, что быстрее.

Тебе действительно очень все равно.

3 голосов
/ 20 августа 2010

На самом деле, другой способ будет

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

, так как b будет установлен на default(bool) (false), если TryParse завершится неудачно.

И b ДОЛЖНЫ быть установлены TryParse, потому что это переменная out.

Не оптимизируйте микро, код, чтобы он читался.

3 голосов
/ 20 августа 2010

Первый вариант немного лучше, потому что он использует меньше кода, поэтому я бы с этим согласился.

Я сомневаюсь, что между этими двумя скоростями существует большая разница, но если вам действительно все равно, вы должны профилировать их обоих - запустите каждый миллион или около того и запишите время выполнения.

2 голосов
/ 20 августа 2010

Разница в скорости между ними будет бесконечно мала по сравнению со стоимостью жизненного цикла страницы.Основная проблема с ними обоими - они не очень читабельны.Почему бы вам просто не сделать следующее:

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

Он достигает того же конца и полностью ясенЯ не вижу никакой ценности в том, что вы делаете, это просто сбивает с толку.

0 голосов
/ 20 августа 2010

В этом случае это не будет иметь никакого существенного значения вообще. Разбор строки занимает так много времени, что небольшая разница между операторами не имеет значения.

В случае, если это будет иметь какое-либо значение, вы должны профилировать код, чтобы знать, какой из них на самом деле быстрее Реальная производительность зависит не только от одного оператора, но и от того, какие операции выполняются до и после этой точки в коде.

Обоснованное предположение состоит в том, что оператор && несколько быстрее. Поскольку нет условного перехода, он лучше подходит для параллельной обработки последовательных операций, чем современные процессоры.

...