Действительно ли эти 2 оператора идентичны?

Следующие 2 фрагмента кода достигают того же самого?

Мой исходный код:

if (safeFileNames != null)
{
    this.SafeFileNames = Convert.ToBoolean(safeFileNames.Value);
}
else
{
    this.SafeFileNames = false;
}

То, что думал ReSharper, было лучшей идеей:

this.SafeFileNames = safeFileNames != null && 
                     Convert.ToBoolean(safeFileNames.Value);

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

Также, если Вы смотрите на: Convert.ToBoolean(safeFileNames.Value); раздел, затем конечно, это могло вызвать исключение нулевой ссылки?

this.SafeFileNames = bool

Локальный safeFileNames является пользовательским объектом со строгим контролем типов, вот класс:

public class Configuration
    {
        public string Name
        {
            get;
            set;
        }
        public string Value
        {
            get;
            set;
        }
    }
6
задан Kara 6 May 2014 в 17:25
поделиться

8 ответов

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

24
ответ дан 8 December 2019 в 02:21
поделиться

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

5
ответ дан 8 December 2019 в 02:21
поделиться

Это снижает цикломатическую сложность вашего кода с помощью предложения resharper.

Независимо от того, легче это читать или нет, это личное мнение, однако я предпочитаю предложение, которое вам дал resharper.

1243] Они идентичны, и если вам нужна удобочитаемость, я мог бы также предложить следующее:

if (safeFileNames != null)
    this.SafeFileNames = Convert.ToBoolean(safeFileNames.Value);
else
    this.SafeFileNames = false;

или

this.SafeFileNames = safeFileNames != null ? Convert.ToBoolean(safeFileNames.Value) : false
2
ответ дан 8 December 2019 в 02:21
поделиться

Они такие же. && - это сокращающий оператор, поэтому вторая половина выражения не будет оценивать, если safeFileNames имеет значение null.

1
ответ дан 8 December 2019 в 02:21
поделиться

Вот IL для обоих фрагментов кода. Я взял ваш код и создал консольное приложение, чтобы взглянуть на IL. Как видно из результирующего IL, один метод (method2) на 4 байта короче, но IL, который работает для обоих, в значительной степени одинаков, поэтому с точки зрения производительности ... не беспокойтесь об этом. У них обоих будет одинаковая производительность. Сосредоточьтесь на том, какой из них легче читать и лучше демонстрирует ваши намерения.

Мой код:

class Program
{
    static void Main(string[] args)
    {


    }
    public void method1()
    {
        bool? safeFileNames = null;

        if (safeFileNames != null)
        {
            SafeFileNames = Convert.ToBoolean(safeFileNames.Value);
        }
        else
        {
            SafeFileNames = false;
        }
    }
    public void method2()
    {
        bool? safeFileNames = null;
        SafeFileNames = safeFileNames != null && Convert.ToBoolean(safeFileNames.Value);
    }
    public static bool SafeFileNames { get; set; }
}

IL для метода 1:

.method public hidebysig instance void  method1() cil managed
{
  // Code size       42 (0x2a)
  .maxstack  1
  .locals init ([0] valuetype [mscorlib]System.Nullable`1<bool> safeFileNames)
  IL_0000:  ldloca.s   safeFileNames
  IL_0002:  initobj    valuetype [mscorlib]System.Nullable`1<bool>
  IL_0008:  ldloca.s   safeFileNames
  IL_000a:  call       instance bool valuetype [mscorlib]System.Nullable`1<bool>::get_HasValue()
  IL_000f:  brfalse.s  IL_0023
  IL_0011:  ldloca.s   safeFileNames
  IL_0013:  call       instance !0 valuetype [mscorlib]System.Nullable`1<bool>::get_Value()
  IL_0018:  call       bool [mscorlib]System.Convert::ToBoolean(bool)
  IL_001d:  call       void ConsoleApplication5.Program::set_SafeFileNames(bool)
  IL_0022:  ret
  IL_0023:  ldc.i4.0
  IL_0024:  call       void ConsoleApplication5.Program::set_SafeFileNames(bool)
  IL_0029:  ret
} // end of method Program::method1

IL для метода2:

.method public hidebysig instance void  method2() cil managed
{
  // Code size       38 (0x26)
  .maxstack  1
  .locals init ([0] valuetype [mscorlib]System.Nullable`1<bool> safeFileNames)
  IL_0000:  ldloca.s   safeFileNames
  IL_0002:  initobj    valuetype [mscorlib]System.Nullable`1<bool>
  IL_0008:  ldloca.s   safeFileNames
  IL_000a:  call       instance bool valuetype [mscorlib]System.Nullable`1<bool>::get_HasValue()
  IL_000f:  brfalse.s  IL_001f
  IL_0011:  ldloca.s   safeFileNames
  IL_0013:  call       instance !0 valuetype [mscorlib]System.Nullable`1<bool>::get_Value()
  IL_0018:  call       bool [mscorlib]System.Convert::ToBoolean(bool)
  IL_001d:  br.s       IL_0020
  IL_001f:  ldc.i4.0
  IL_0020:  call       void ConsoleApplication5.Program::set_SafeFileNames(bool)
  IL_0025:  ret
} // end of method Program::method2
5
ответ дан 8 December 2019 в 02:21
поделиться

Они такие же. В однострочном варианте, если первое условие не выполняется, второе не оценивается. Так что вы не получите нулевую ссылку.

Держу пари, что IL в обоих случаях одинаков.

Я предпочитаю вторую версию.

1
ответ дан 8 December 2019 в 02:21
поделиться

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

Есть несколько других способов сделать то, что вы пытаетесь сделать, могло бы быть более читабельным. Какой тип значения является safeFileNames? Похоже, это может быть nullable bool? Если это так, вы можете просто написать:

this.SafeFileNames = safeFileNames.GetValueOrDefault();
1
ответ дан 8 December 2019 в 02:21
поделиться

Логически они идентичны. Любая разница в производительности, скорее всего, будет незначительной. Возможно, что вторая форма будет преобразована в более эффективный двоичный код на некоторых платформах, поскольку вторая форма устраняет условное выражение. Условные выражения (неправильное спекулятивное выполнение) могут испортить конвейер инструкций вашего процессора при работе с интенсивным использованием процессора. Однако и IL, и JITter должны генерировать код адекватного качества, чтобы это имело большое значение.

Я согласен с вашим ощущением удобочитаемости, но не думаю, что все разделяют это.

0
ответ дан 8 December 2019 в 02:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: