Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Так ли примитивен строковый оператор

Anna | 17.06.2014 | нет комментариев

Вступление

Строковый тип данных является одним из фундаментальных типов, наравне с числовыми (int, long, double) и логическим (bool). Трудно себе представить хоть, сколько либо пригодную программу, не использующую данный тип.

На платформе .NET строковый тип представлен в виде неизменяемого класса String. Помимо того, он является крепко интегрированным в общеязыковую среду CLR, а так же имеет поддержку со стороны компилятора языка C#.

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

Спецификация языка о строковом операторе

Спецификация языка C# предоставляет три перегрузки оператора для строк:

string operator   (string x, string y)
string operator   (string x, object y)
string operator   (object x, string y)

Если один из операндов объединения строк есть null, то подставляется пустая строка. Напротив всякий довод, не являющийся строкой, приводится к представлению в виде строки с поддержкой вызова виртуального способа ToString. Если способ ToString возвращает null, подставляется пустая строка. Следует сказать, что согласно спецификации данная операция никогда не должна возвращать значение null.

Изложение оператора выглядит довольно ясно, впрочем если мы взглянем на реализацию класса String то обнаружим очевидное определение лишь 2-х операторов == и !=. Появляется резонный вопрос, что происходит за кулисами конкатенации строк? Каким образом компилятор обрабатывает строковый оператор ?

Результат на данный вопрос оказался не таким уж трудным. Нужно присмотреться повнимательнее к статическому способу String.Concat. Способ String.Concat — объединяет один либо несколько экземпляров класса String либо представления в виде String значений одного либо нескольких экземпляров Object. Имеются следующие перегрузки данного способа:

public static String Concat(String str0, String str1)
public static String Concat(String str0, String str1, String str2)
public static String Concat(String str0, String str1, String str2, String str3)
public static String Concat(params String[] values)
public static String Concat(IEnumerable<String> values)

public static String Concat(Object arg0)
public static String Concat(Object arg0, Object arg1)
public static String Concat(Object arg0, Object arg1, Object arg2)
public static String Concat(Object arg0, Object arg1, Object arg2, Object arg3, __arglist)	

public static String Concat<T>(IEnumerable<T> values)

Подробнее

Пускай у нас есть следующее выражение s = a b, где a и b — строки. Компилятор преобразует его в вызов статического способа Concat, то есть в

s = string.Concat(a, b)

Операция конкатенации строк, как и любая иная операция сложения в языке C# является лево-ассоциативной.

С двумя строками все ясно, но что если строк огромнее? Выражение s = a b c рассматривая лево-ассоциативность операции могло бы быть заменено на

s = string.Concat(string.Concat(a, b), c)

впрочем, рассматривая присутствие перегрузки, принимающей три довода оно будет преобразовано в

s = string.Concat(a, b, c)

Подобно дела обстоят с конкатенацией четырех строк. Для конкатенации 5 и больше строк имеем перегрузку string.Concat(params string[]), так что нужно рассматривать убыточные расходы, связанные с выделением памяти под массив.

Следует так же сказать, что операция конкатенации строк является всецело ассоциативной: не имеет никакого значения, в каком порядке мы конкатенируем строки, следственно выражение s = a (b c) не смотря на очевидное указание приоритета выполнения конкатенации, обрабатывается как

s = (a   b)   c = string.Concat(a, b, c) 

взамен ожидаемого

s = string.Concat(a, string.Concat(b, c))

Таким образом, подытоживая сказанное выше: операция конкатенации строк неизменно представляется слева направо, и испольpermark! string.FillStringChecked(dest, str0.Length, str1); string.FillStringChecked(dest, str0.Length str1.Length, str2); return dest; }

Оператор в Java


Пару слов о строковом операторе в Java. Правда я и не программирую на Java, увлекательно все же знать, как дела обстоят там. Компилятор языка Java оптимизирует оператор , так что он использует класс StringBuilder и вызов способа append.

Предшествующий код преобразуется в

String fio = new StringBuilder(String.valueOf(surname)).append(name).append(patronymic).ToString()


Стоит так же сказать, что от такой оптимизации в C# отказались специально, у Эрика Липперта естьпост на эту тему. Дело в том, что такая оптимизация не является оптимизацией как таковой, она является переписыванием кода. Плюс к этому создатели языка C# считают, что разработчики обязаны знать особенности работы с классом String и в случае необходимости перейдут на применение StringBuilder.

Кстати именно Эрик Липперт занимался оптимизациями компилятора C#, связанными с конкатенацией строк.

Завершение


Допустимо, на 1-й взор может показаться необычным, что класс String не определяет оператор , пока мы не подумаем о вероятностях оптимизации компилятора, связанных с видимостью большего фрагмента кода. Скажем, если бы оператор был определен в классе String, то выражение s = a b c d приводило бы к созданию 2-х промежуточных строк, исключительный вызов способа string.Concat(a, b, c, d) разрешает исполнить объединение больше результативно.

 

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB