2016-07-18 4 views
0

В одном из нашего приложения я пришел через несколько строк, как это:Console.WriteLine() против Console.WriteLine (string.Empty)

Console.WriteLine(string.Empty); 

Я проверил, имеет ли какой-либо разницы, если я просто напишите:

Console.WriteLine(); 

Но выход такой же (как и ожидалось).

Что такое «лучшая практика» в этом примере? Есть ли ситуации, когда необходимо пропускать пустой string вместо того, чтобы не передавать какой-либо параметр?

+7

Сколько это действительно имеет значение? –

+0

Это вопрос предпочтения, я думаю, но технически нет никакой разницы. –

+3

Вы забыли упомянуть 'Console.Write (System.Environment.NewLine);' – fubo

ответ

7

WriteLine() реализуется следующим образом:

public virtual void WriteLine() { 
    Write(CoreNewLine); 
} 

WriteLine(string) однако реализуется следующим образом:

public virtual void WriteLine(String value) { 
    if (value==null) { 
     WriteLine(); 
    } 
    else { 
     // We'd ideally like WriteLine to be atomic, in that one call 
     // to WriteLine equals one call to the OS (ie, so writing to 
     // console while simultaneously calling printf will guarantee we 
     // write out a string and new line chars, without any interference). 
     // Additionally, we need to call ToCharArray on Strings anyways, 
     // so allocating a char[] here isn't any worse than what we were 
     // doing anyways. We do reduce the number of calls to the 
     // backing store this way, potentially. 
     int vLen = value.Length; 
     int nlLen = CoreNewLine.Length; 
     char[] chars = new char[vLen+nlLen]; 
     value.CopyTo(0, chars, 0, vLen); 
     // CoreNewLine will almost always be 2 chars, and possibly 1. 
     if (nlLen == 2) { 
      chars[vLen] = CoreNewLine[0]; 
      chars[vLen+1] = CoreNewLine[1]; 
     } 
     else if (nlLen == 1) 
      chars[vLen] = CoreNewLine[0]; 
     else 
      Buffer.InternalBlockCopy(CoreNewLine, 0, chars, vLen * 2, nlLen * 2); 
     Write(chars, 0, vLen + nlLen); 
    } 
} 

Если вы называете это с null строки, то вы получите тот же результат, как и для WriteLine() без аргументы (плюс дополнительный вызов метода). Однако логика при передаче непустой строки немного сложнее.

Для string.Empty это выделит новый массив символов длиной 2 и скопирует новый символ строки.

Это, как правило, не дорого, но все же несколько избыточно, если вы не хотите ничего печатать. Специально для фиксированный звонки на номер Console.WriteLine не имеет смысла проходить string.Empty.

Вы должны предпочесть Console.WriteLine() над Console.WriteLine(string.Empty), если только для простоты.

1

Нет никакой разницы для меня с технической стороны. Это то, как разработчик находит его удобным и читаемым. Для меня Console.WriteLine() более интуитивно понятен, что он пишет пустую строку, а Console.WriteLine(String.Empty) заставляет меня остановиться и подумать на секунду (может быть, меньше).

Любые другие варианты: IMO, акт создания кода и не использовать его в профессиональном коде производства.

1

Из ссылки (https://msdn.microsoft.com/en-us/library/system.console.writeline(v=vs.110).aspx)

еЫпе (строка): Записывает заданное значение строки, а затем текущего конца строки, в стандартный выходной поток.

WriteLine(): Записывает текущий ограничитель строки в стандартный выходной поток.

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

2

Лучшей практикой является использование более читаемого Console.WriteLine();.

Несмотря на то, что нет семантического различия, вы будете выполнять unnecessary code, если вы пишете Console.WriteLine(string.Empty);:

public virtual void WriteLine(String value) { 

    if (value==null) { 
     WriteLine(); 
    } 
    else { 
     // We'd ideally like WriteLine to be atomic, in that one call 
     // to WriteLine equals one call to the OS (ie, so writing to 
     // console while simultaneously calling printf will guarantee we 
     // write out a string and new line chars, without any interference). 
     // Additionally, we need to call ToCharArray on Strings anyways, 
     // so allocating a char[] here isn't any worse than what we were 
     // doing anyways. We do reduce the number of calls to the 
     // backing store this way, potentially. 
     int vLen = value.Length; 
     int nlLen = CoreNewLine.Length; 
     char[] chars = new char[vLen+nlLen]; 
     value.CopyTo(0, chars, 0, vLen); 
     // CoreNewLine will almost always be 2 chars, and possibly 1. 
     if (nlLen == 2) { 
      chars[vLen] = CoreNewLine[0]; 
      chars[vLen+1] = CoreNewLine[1]; 
     } 
     else if (nlLen == 1) 
      chars[vLen] = CoreNewLine[0]; 
     else 
      Buffer.InternalBlockCopy(CoreNewLine, 0, chars, vLen * 2, nlLen * 2); 
     Write(chars, 0, vLen + nlLen); 
    } 
    /* 
    Write(value); // We could call Write(String) on StreamWriter... 
    WriteLine(); 
    */ 
} 

Там есть выделение буфера и струнная копия там. Было бы лучше, если бы они написали if (string.IsNullOrEmpty(value)), но по какой-то причине они этого не сделали.

В то время как простой способ is just:

public virtual void WriteLine() { 
    Write(CoreNewLine); 
} 

(CoreNewLine является char[])

+0

', но по какой-то причине они не были - вероятно, потому, что никто никогда не говорил:« О, моя программа только что снизилась на 0,0001мс из-за того, что было выделено буфером ». – Enigmativity

+0

@ Енигматизм, вероятно, да;) –

1

Как вы можете видеть на tryroslyn

C# код:

using System; 
public class C { 
    public void M() { 
     Console.WriteLine();  
     Console.WriteLine(String.Empty); 
    } 
} 

Генерирование IL код :

.class private auto ansi '<Module>' 
{ 
} // end of class <Module> 

.class public auto ansi beforefieldinit C 
    extends [mscorlib]System.Object 
{ 
    // Methods 
    .method public hidebysig 
     instance void M() cil managed 
    { 
     // Method begins at RVA 0x2050 
     // Code size 19 (0x13) 
     .maxstack 8 

     IL_0000: nop 
     IL_0001: call void [mscorlib]System.Console::WriteLine() 
     IL_0006: nop 
     IL_0007: ldsfld string [mscorlib]System.String::Empty 
     IL_000c: call void [mscorlib]System.Console::WriteLine(string) 
     IL_0011: nop 
     IL_0012: ret 
    } // end of method C::M 

    .method public hidebysig specialname rtspecialname 
     instance void .ctor() cil managed 
    { 
     // Method begins at RVA 0x2064 
     // Code size 8 (0x8) 
     .maxstack 8 

     IL_0000: ldarg.0 
     IL_0001: call instance void [mscorlib]System.Object::.ctor() 
     IL_0006: nop 
     IL_0007: ret 
    } // end of method C::.ctor 

} // end of class C 

Так линия Console.WriteLine(String.Empty); получает значение из string.Empty и передать его функционирования. Лучше Console.WriteLine() меньше операций.

+2

Хотя запись на консоль настолько медленная, что никто не заметит разницы. –

+1

Наличие еще одной операции ИИ для чтения статического члена на самом деле не является достаточным основанием для предпочтения одного вызова над другим. Чтение вызова является гораздо более убедительным аргументом, и если вы хотите поспорить с помощью внутренних компонентов (код IL и т. Д.), Вы должны посмотреть на реализации методов, которые вы вызываете. – poke

Смежные вопросы