Который работает быстрее Null coalesce, Ternary или If Statement [closed]

Мы используем?? оператор оценить выражения по нулевым значениям, например:

string foo = null;
string bar = "woooo";
string foobar= foo ?? bar ; 
// Evaluates foobar as woooo

Мы также использовалиif оператор, который работает так же, если используется с выражением выше

string foo = null;
string bar = "woooo";
if(foo==null)
   string foobar=   "woooo" ;
// Evaluates foobar as woooo same as above

А также?: Троичный оператор...

string foo = null;
string bar = "woooo";    
string foobar= foo==null ? "woooo" : null ;
// Evaluates foobar as woooo same as above

Я знаю, что нулевое объединение является точным в синтаксисе, но какой из них компилируется быстрее среди обоих и выполняется быстрее и почему?

 asawyer14 нояб. 2012 г., 20:35
@comecme Это 'Хуже того:Embedded statement cannot be a declaration or labeled statement
 Servy14 нояб. 2012 г., 20:12
Если это вызывает проблемы с производительностью вашего кода, у вас гораздо большие проблемы.
 Amitd14 нояб. 2012 г., 20:04
это больше похоже на синтаксический сахар ..
 Nick Vaccaro14 нояб. 2012 г., 20:04
Если ты'Что касается времени выполнения, C # может быть не лучшим выбором.
 James Michael Hare15 нояб. 2012 г., 16:20
Странно, что это было закрыто какне реальный вопросКазалось, хороший вопрос для меня. Я думаю "перформанс первый " как правило, это неправильная стратегия, но этоЭто все еще актуальный вопрос в моей книге.
 James Michael Hare14 нояб. 2012 г., 20:09
Технически, вы должны сравнивать?? в?: не дляif как?: гораздо более логично подходит для?? чемif является.
 nawfal29 янв. 2014 г., 02:44
возможный дубликатstackoverflow.com/questions/1543522/...
 Mayank Pathak14 нояб. 2012 г., 20:15
@Servy Нет, с точки зрения производительности я нашел их одинаковыми .. но я подумал, зачем нужна точная альтернатива .. я знаю его синтаксически более точным, чем если бы… я просто хотел узнать лучший ответ, используя оба утверждения в другой способсидеть...
 Servy14 нояб. 2012 г., 20:23
@MayankPathak Вы должны интересоваться только производительностью какого-либо блока кода, когда выМы показали, что у вас есть проблемы с этой конструкцией или методом. "Преждевременная оптимизация - корень всего зла ".
 comecme14 нояб. 2012 г., 20:30
Второй пример кодане так же, как первый! Еслиfoo не являетсяnullпервый пример назначитfoo вfoobar, Ваш второй пример нет.

Ответы на вопрос(2)

Они оба должны скомпилировать один и тот же IL и, таким образом, выполнить то же самое.

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

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

 asawyer14 нояб. 2012 г., 20:33
@JustinNiessner How 'с этим взглядом:pastebin.com/F1wHfQNM
 asawyer14 нояб. 2012 г., 20:21
@JustinNiessnerpastebin.com/DqXqk3Nm  (С отключенной оптимизацией)
 James Michael Hare14 нояб. 2012 г., 20:08
Я согласен с частью об использовании ясного синтаксиса, но?? Оператор на самом деле компилирует меньше IL.
 Justin Niessner14 нояб. 2012 г., 20:09
@JamesMichaelHare - Правда? Тот'удивительно К сожалению я неУ меня есть что-то передо мной, я могу посмотреть ... чтоРазница?
 Justin Niessner14 нояб. 2012 г., 20:24
@asawyer - Есть ли шанс, что вы также можете опубликовать IL для метода, который принимает параметр, а не определяет все статически? Похоже, компилятор мог оптимизировать этот IL.
Решение Вопроса

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

На самом деле вы должны сравнить?? в?: и неif так как они имеют разные цели. Да они все в какой то формеусловно» Боже мой, но ключ в том, что оба?? а также?: оценить значение, тогда какif нет, поэтому они часто имеют различное использование.

Например, следующий код:

Console.WriteLine("The order} is for {1} product",
    orderId, productId ?? "every");

Было бы неудобнее писать с:if

if (productId == null)
{
    Console.WriteLine("The order {0} is for every product",
        orderId);
}
else
{
    Console.WriteLine("The order {0} is for {1} product",
        orderId, productId);
}

Да, вы можете сгущаться до одного, но тогда выиметь временную переменную и т.д .:

if (productId == null)
{
    productId = "every";
}

Console.WriteLine("The order {0} is for {1} product",
    orderId, productId);

Таким образом, на самом деле, вы не должныT сравнить два, потому что они указывают на?? должен оценить значение, если аргументnullтогда как точкаif должен выполнить другой путь (не приводящий непосредственно к значению.

Таким образом, лучший вопрос может быть, почему бы не это:

Console.WriteLine("The order {0} is for {1} product",
    orderId, productId == null ? "every" : productId);

Что во многом одинаково (оба оценивают по значению) и не так много для управления потоком.

Так что давайте'смотри на разницу. Позволять's написать этот код тремя способами:

// Way 1 with if
string foo = null;
string folder = foo;

if (folder == null)
{
    folder = "bar";
}

// Way 2 with ? :
string foo2 = null;
var folder2 = foo2 != null ? foo2 : "bar";

// Way 3 with ??
string foo3 = null;
var folder3 = foo3 ?? "bar";

Для IF мы получаем следующий IL:

IL_0001:  ldnull      
IL_0002:  stloc.0     
IL_0003:  ldloc.0     
IL_0004:  ldnull      
IL_0005:  ceq         
IL_0007:  ldc.i4.0    
IL_0008:  ceq         
IL_000A:  stloc.1     
IL_000B:  ldloc.1     
IL_000C:  brtrue.s    IL_0016
IL_000E:  nop         
IL_000F:  ldstr       "bar"
IL_0014:  stloc.0     

Для условного (? :) мы получаем следующий IL:

IL_0001:  ldnull      
IL_0002:  stloc.0     
IL_0003:  ldloc.0     
IL_0004:  brtrue.s    IL_000D
IL_0006:  ldstr       "bar"
IL_000B:  br.s        IL_000E
IL_000D:  ldloc.0     
IL_000E:  nop         
IL_000F:  stloc.1   

Для null-colelescing (??) мы получаем этот IL:

IL_0001:  ldnull      
IL_0002:  stloc.0     
IL_0003:  ldloc.0     
IL_0004:  dup         
IL_0005:  brtrue.s    IL_000D
IL_0007:  pop         
IL_0008:  ldstr       "bar"
IL_000D:  stloc.1    

Заметьте, как каждый последующий проще?if больше IL, потому что ему нужна логика ветвления для обработки отдельных операторов.?: меньше, потому что он просто оценивает значение (не переходя к другим операторам), но все еще должен загрузить операнд для сравнения с (null).

?? является самым простым из всех, потому что есть инструкция IL для сравнения сnull (против загрузкиnull и сравнивая с этим.

ТАК все это сказал, тыМы говорим об очень небольшой разнице в терминах IL, которая может влиять или не влиять на производительность. Независимо от этого, скорее всего, это будет иметьочень Небольшое существенное отличие по сравнению с более интенсивной работой в программе (математика, база данных, сеть и т. д.).

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

Для меня реальная причина использовать?: или же?? когда вы хотите, чтобы конечный результат был значением. То есть в любое времяхотелось бы написать:

if (someCondition)
    x = value1;
else 
    x = value2;

Затем я'буду использовать условное (?:) потому что это - то, для чего это является большим сокращением.x получает одно или другое значение на основе этого условия ...

Затем я'буду идти еще дальше с?? и сказать, что то же самое верно, вы хотите присвоить значение переменной на основеnull-идентификатора.

Такif отлично подходит для управления потоком, но если вы просто возвращаете одно из двух значений или присваиваете одно из двух значений на основе условия, ябуду использовать?: или же?? по мере необходимости.

в заключение имейте в виду, как эти вещи реализованы под прикрытием (IL и связанная с ними производительность) могут меняться с каждой ревизией .NET Framework (на момент написания этой статьи они все настолько близки, что их можно было пренебречь).

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

ОБНОВИТЬ

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

10,000,000 iterations of:
?: took: 489 ms, 4.89E-06 ms/item.
?? took: 458 ms, 4.58E-06 ms/item.
if took: 641 ms, 6.41E-06 ms/item.
 comecme14 нояб. 2012 г., 20:34
way1 и way3 одинаковы (код C #)
 James Michael Hare14 нояб. 2012 г., 20:35
извините, вырезать и вставить ошибку, исправлено ...
 Mayank Pathak15 нояб. 2012 г., 06:40
@JamesMichaelHare Очень подробный ответ, спасибо, это действительно помогло .. :) +1 и принимаю это как ответ ..
 Mayank Pathak14 нояб. 2012 г., 20:21
я должен был назначитьfoobar к некоторому значению, как я уже упоминал в приведенных выше примерах .. таким образом, я использовалif по моему сценарию. используя троичный я нет нашел подходящий ..
 Mayank Pathak15 нояб. 2012 г., 06:42
И я'Я также обновляю свой вопрос, так как согласно вашему ответу это будет более полезным .. :)
 Krease15 нояб. 2012 г., 00:47
Вау, очень подробный ответ!

Ваш ответ на вопрос