c # распечатка конкатенации строк - PullRequest
4 голосов
/ 17 декабря 2010

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

string temp = "test";

        Console.WriteLine("this is a " + temp);
        Console.WriteLine("this is a {0}", temp);

Есть ли какое-либо преимущество / ущерб, если использовать одно преимущество над другим или оно просто зависит от предпочтений?

Спасибо.

Ответы [ 6 ]

4 голосов
/ 17 декабря 2010

РЕДАКТИРОВАНИЕ: Мой оригинальный ответ только что указал на IL для двух методов;я хотел предложить Даррену взять их за отправную точку.Ани (комментарии) предположила, что этого недостаточно для четкого ответа.Я тоже решил посмотреть, поэтому разместил здесь схему процесса, который я предлагал Даррену, который, как мы надеемся, показывает процесс, который нужно пройти, и показывает, как другие могли бы сразу сказать: «o, x использует строку:: format ".

Итак: наивно я ожидал бы, что первое будет более эффективным, поскольку все, что нужно CLR, - это объединение двух строк, тогда как второе использует обобщенный метод, который принимает объект и, следовательно, долженпреобразовать этот объект в строку.Даже если это преобразование является тривиальным, ему все равно нужно пройти через некоторые операции, чтобы добраться до вызова, прежде чем окончательно обнаружить, что строка не нуждается в преобразовании.Я посмотрел на IL, используя ildasm , чтобы увидеть, что происходит - в равной степени мы могли бы использовать Reflector , который потенциально мог бы быть более читабельным.

Для чего это стоит- Я думаю, что я буду использовать StringBuilder.Append с самого начала, в любом случае.

В первом (+) экземпляре у нас есть вызов String :: Concat (string, string) (который делаетпочти то, что вы ожидаете, если вы посмотрите на IL), за которым следует Console.WriteLine (строка).

  IL_000d:  call       string [mscorlib]System.String::Concat(string,
                                                              string)
  IL_0012:  call       void [mscorlib]System.Console::WriteLine(string)

Console.WriteLine (строка) эффективно просто вызывает TextWriter :: WriteLine (строка),Вот вам и первый метод.

Второй метод вызывает Console.WriteLine (string, object):

  IL_000d:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)

Если мы разберем Console :: WriteLine (в mscorlib), мы увидим, что он вызываетTextWriter :: WriteLine (string, object):

.method public hidebysig static void  WriteLine(string format,
                                                object arg0) cil managed
...
  IL_0007:  callvirt   instance void System.IO.TextWriter::WriteLine(string,
                                                                     object)

, который в разобранном виде вызывает String :: Format (...):

.method public hidebysig newslot virtual 
        instance void  WriteLine(string format,
                                 object arg0) cil managed
...
  IL_0014:  call       string System.String::Format(class System.IFormatProvider,
                                                    string,

В этом случае String ::Формат фактически создает StringBuilder с начальной строкой:

.method public hidebysig static string  Format(class System.IFormatProvider provider,
                                               string format,
...
  IL_0027:  newobj     instance void System.Text.StringBuilder::.ctor(int32)

, затем должен вызвать StringBuilder :: AppendFormat с объектом

  IL_0031:  callvirt   instance class System.Text.StringBuilder System.Text.StringBuilder::AppendFormat(class System.IFormatProvider,
                                                                                                        string,
                                                                                                        object[])

, чтобы заполнить его.Затем StringBuilder :: AppendFormat должен преобразовать объект, чтобы он мог добавить его в виде строки перед окончательным вызовом TextWriter :: WriteLine (string).

Суммируя этот лот, оба в конечном итоге вызывают TextWriter :: WriteLine (string)Таким образом, они отличаются тем, что первые звонки

String::Concat(string, string) 

и вторые звонки

Console::WriteLine(string, object), 
TextWriter::WriteLine(string, object)
String::Format(...).  
String::StringBuilder().ctor
String::StringBuilder().AppendFormat(...)

(и водопровод) в основном выполняют ту же работу.

ЕстьУдивительная сумма происходит под капотом во втором.StringBuilder :: ApendFormat - это, пожалуй, самая сложная часть из всех, и на самом деле мой IL недостаточно хорош, чтобы определить, есть ли у него ранние escape-символы, если, например, он обнаружит, что переданный объект является строкой ... но тот факт, чтоон должен учитывать, что это означает, что он должен сделать некоторую дополнительную работу.

Итак, между этими двумя понятиями есть различия.Первый выглядит более эффективно, если вы знаете, что вам нужно объединить две строки, что может быть полезным.Было бы интересно взглянуть на то, как первое сравнивается с использованием StringBuilder с самого начала.

Комментарии и исправления приветствуются ... и надеюсь, что это поможет прояснить мой ответ.

4 голосов
/ 17 декабря 2010

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

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

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

Console.WriteLine("this is a " + temp + "." );
vs
Console.WriteLine("this is a {0}.", temp);
2 голосов
/ 17 декабря 2010

Однако есть некоторые отличия.

Первая строка создает новую строку, а затем отправляет ее в метод WriteLine.

Во второй форме WriteLine внутренне вызывает string.Format (), которая внутренне использует StringBuilder для построения окончательной строки, которая будет записана.

В некоторых случаях может быть лучше использовать вторую форму (особенно при наличии более одного аргумента).

2 голосов
/ 17 декабря 2010

В этом случае first one более читабельно.С точки зрения производительности также, вероятно, чуть быстрее, поскольку есть только один параметр.

Использование + сцепления становится нечитаемым с несколькими параметрами в середине стента.

Второй использует String.Format(...) который внутренне использует StringBuilder.

2 голосов
/ 17 декабря 2010

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

Это вопрос предпочтения.

Лично я бы пошел с версией + в этом случае - она ​​короче, но одинаково читабельна.Строки форматирования действительно блестят, когда требуется более сложное форматирование, чем эта тривиальная конкатенация, например, если вам нужны произвольные символы в middle требуемого вывода.Как указывает SWeko, форматная версия обеспечивает простоту сопровождения, но это не является решающим моментом, насколько я понимаю (нетрудно перейти с одной версии на другую; даже лучше, инструмент, такой как Resharper, может это сделать.от вашего имени).

Я хотел бы отметить один (неактуальный для 90% случаев) факт: версия + вероятно будет несколько более производительной, так как нет строки форматабыть проанализированным во время выполнения.(Как и в случае любой другой проблемы с производительностью, вам необходимо измерить свои конкретные случаи, чтобы оправдать выбор одного над другим.)

1 голос
/ 17 декабря 2010

читаемость

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

Performance

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...