C# Почему при создании строки ключевое слово new можно не использовать?
Как известно, в C# для фактического создания объектов предназначено ключевое слово new. Но почему при создании строки это слово можно не использовать? Т.е. можно написать так:
string a = «привет»;
В MSDN смотрел, там написано: «Обратите внимание, что для создания строкового объекта оператор new не используется, за исключением случаев инициализации строки массивом символов».
Только учтите, меня интересуют не мотивы разработчиков, по которым они дали возможность опускать ключевое слово new, а как они это сделали (и как это можно сделать самому, для своего класса).
21 коментар
Додати коментар Підписатись на коментаріВідписатись від коментарівпри чём вполне уместный, хоть и рожает заблуждение в умах новичков что string это value type.
bonifatio, спасибо)
gif0, посмотрите все подробности например в MSDN. Если коротко, то у строки переопределены только операции == и! =. Конкатенация с помощью + это опять тот самый пресловутый syntactic sugar. В результате компилятор заменяет эту операцию на вызов
Почему все так… Строки используются очень часто и поэтому вполне понятно, почему CLR с ними обращается не так, как с другими объектами — так более эффективно. По крайней мере мне хочется верить, что JIT-компилятор генерирует оптимальный машинный код для всех чисто строчных команд:)
ЗЫ. Троелсен — это хорошо, но ваши вопросы не всегда освещаются даже в более сложных книгах типа Рихтера, так что лучше всего будет все детали увидеть в IL-коде самому. ildasm и Reflector смогут вам в этом помочь:)
Сашка, я имею в виду, почему нет перезагрузки операторов «+», «-», «=» и т.п., а вместо них (перезагрузок) какие-то CIL инструкции, выполняющие те же функции (если я правильно понял bonifatio).
public static implicit operator string (string str)
{
return str; }
>>> Може все таки варто спочатку щось базове вивчити
Я и изучаю «щось базове». Это не сложно понять с моего сообщения, которое вы процитировали.
Сашка, я понял, но почему для строки никакие перегрузки не используются?
int [] numbers = {1, 2, 3, 4, 5}; // здесь тоже можно без new
Сашка, просто идеологию хочу понять
Може все таки варто спочатку щось базове вивчити, а тоді вже виявляти незадоволення чимось...
Зачем нужен какая-то перегрузка для string a = «привет»; если компилятору и так видно что строка в обеих частях выражения? Или ты уже про какой-то другой смысл интересуешься?
bonifatio, почему для строки никакие перегрузки не используются? Разве это правильно, какой в этом смысл?
-
Да, для строки никакие перегрузки не используются. Для того кода, который я привел, вIL-коде появится дополнительный вызов вида
ЗЫ. StringImplicitConversion — это пространство именbonifatio, отдельное спасибо за четкое объяснение. Как я понял, в С# можно не использовать ключевое слово new для объектов класса string, но не потому, что оператор «=» у него перезагружен, а из-за особых CIL инструкций?
Вопрос в том, что именно Вы хотите, чтобы получилось? что именно дожно стоять справо от знака равно? В принципе, кое-что такое сделать можно, но смысла в этом я особо не вижу. Например, можно создать у класса implicit conversion operator из какого-нибудь простого типа данных, вроде строки и тогда можно будет писать что-то вроде:
Но, конечно, проблем тут не оберёшься, ибо все ошибки будут ловиться не компилятром, а в рантайм.2Tim: Можно генерировать любые команды с помощью классов из пространства имен Reflection.Emit, вопрос только зачем:)
Упс, не заметил «меня интересуют не мотивы разработчиков». Наверное сами не сможете, нужны новые команды IL + чтоб компилятор понял что от него хотят. Возможно CLR и допускает возможость своего кастомайзинга, никогда таким не заморачивался.
2. Конструктор явно можно вызвать только для создания строки из массива символов (в том числе можно передать char*, если нужно работать с неуправляемым кодом), в остальных случаях нужно использовать инициализатор.
3. Если есть необходимость писать что-то вроде такого:
то вам нужно определить неявное преобразование. Например, вот так:string a = «aaa»;
string b = a + «bb»;
bool equal = object.ReferenceEquals (a, b);
equal будет false, так как обьекты «a» и «b» имеют разные адреса. Если нужно много манипуляций с string, лучше воспользоваться классом StringBuilder. Более полную инфу можете гялнуть в книге «CLR via C#» имхо одна из лучших книг по C# и.NET.
Я не очень разбираюсьь в C#, но такое у меня запустилось:
саме так це реалізовано в Delphi...
Не знаю, як це зроблено у C#-ному String, і взагалі не знаю C#, але знання C++ підказують, що таке можна реалізувати, якщо в імплементації перевизначеного оператора присвоєння міститься new, а в імплементації перегруженого деструктора — delete.