Почему новая строка («Hello») недопустима в C #?

#c# #.net #string #constructor

#c# #.net #строка #конструктор

Вопрос:

Какова логика / причина создания

 String s= new String("Hello World");
  

Недопустимо в C #?
Ошибка

Лучший перегруженный метод соответствует `string.String(char *)’ имеет некоторые недопустимые аргументы

Меня не интересуют документы API, меня интересует, почему это незаконно.

Это из-за объединения статических строк? например, Java объединяет целое число (-128) в целое число (127) с ужасающими результатами? (конечно, строки тоже)

Комментарии:

1. Потому что класс string не содержит конструктора, принимающего один строковый аргумент?

2. (В Java есть new String(String) конструктор — это особенно полезно для академической игры с «новыми строковыми объектами» и «интернированными строковыми объектами», поскольку строки Java не перегружаются == … в любом случае, поскольку она есть в Java , почему не в C #? Я надеюсь, что некоторые ответы могут попытаться решить эту проблему, если она адресуема по какой-либо разумной причине [кроме того, что она не была признана полезной / необходимой].)

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

4. @CaptainGiraffe: Пожалуйста, не соглашайтесь! В чем убедительная выгода для клиентов от «создания новой ссылки» на строку? Бывали дни, когда мне очень нужно было «создать клонированную копию состояния этого IEnumerator», но я ни разу не сказал себе: «Мне нужно иметь две строки, которые идентичны во всех отношениях, кроме их управляемого адреса, тем самым гарантированно занимая в два раза больше места, чем необходимов памяти». Я не вижу здесь преимущества.

5. @pst: Каким образом «потому что у Java есть это» каким- либо образом оправдывает функцию в C #? Возможности в C # оправданы их неоспоримыми преимуществами для наших клиентов. (И я отмечаю, что наиболее очевидная особенность C #, которая существует «потому, что она есть в Java» — ковариация массива — глубоко нарушена и вызывает серьезные проблемы с производительностью и корректностью.) Я полагаю, у разработчиков Java была какая-то причина добавить эту функцию; спросите их, хотите ли вы получить их объяснение. Я не эксперт по Java, поэтому понятия не имею, почему в Java есть такая функция.

Ответ №1:

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

 string s = "Hello World";
  

Комментарии:

1. Итак, почему в Java существует такая конструкция? 😉

2. Я думал, что конструкторы копирования полезны.

3. @Captain Giraffe Какой смысл копировать объект, который никогда не может быть изменен? 🙂

4. @supercat: вы имеете в виду строковую переменную , а не строку. Переменная, конечно, может указывать на другую строку, но сама строка остается неизменной

5. @Captain Giraffe == (как и все операторы) не является полиморфным. object.==(object) является идентификатором объекта. Однако string.==(string) это равенство значений. Это резко контрастирует с Java (которая не имеет == перегрузки).

Ответ №2:

Потому что строки неизменяемы и имеют языковую поддержку в том, как они создаются.

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

Комментарии:

1. Почему неизменность строк вообще вступает в игру?

2. Вы создаете строку из строки — обе идентичны и не могут быть изменены. В чем смысл? Просто используйте исходную строку.

3. Аргумент объединения — единственный надежный аргумент, который я нашел до сих пор. Спасибо.

Ответ №3:

Это .NET, а не C #. Посмотрите на конструкторы для System .Строка — нет принимает систему.Строка

Так что это «незаконно» по той же причине, по которой вы не можете создать строку с помощью int .

 string x = new String(1);
  

Рэймонд Чен

Ответ на вопрос «Почему эта функция не существует?» обычно звучит так: «По умолчанию функции не существуют. Кто-то должен их реализовать «.


Я предполагаю, что каждый раз, когда кто-то садился за реализацию этого конструктора. Они подумали о строке.Реализация toString и определила, что конструктор логически подорвет этот метод.

Комментарии:

1. Я хочу сказать, что никто не делал это незаконным. Они просто не указали конструктор, который вы ожидаете увидеть там. Вопрос «Почему», который вы должны задать, звучит так: «Почему вы ожидаете, что она будет там?». Если это потому, что вы пришли из мира Java, тогда добро пожаловать в .Net — здесь все по-другому.

2. Нет, если что, я из мира c . Но я ценю приветствие =)

3. 1 Не обижайтесь на остальных, но я считаю, что этот пост заслуживает большего количества голосов, чем остальные

Ответ №4:

Это создало бы впечатление, что строка клонируется, но строки неизменяемы.

Комментарии:

1. Они не обязательно ортогональны, но сильно связаны.

Ответ №5:

Строка неизменяема, пока вы не начнете возиться с небезопасным кодом, поэтому разработчики языка решили не добавлять функцию, которая не нужна при обычном использовании. Это не значит, что это не было бы удобно в определенных ситуациях.

Если вы сделаете это:

 string a = "foobar";
string b = a;
Mutate(a, "raboof");
Console.WriteLine("b={0}", b);
  

где:

 unsafe void Mutate(string s, string newContents)
{
    System.Diagnostics.Debug.Assert(newContents.Length == s.Length);
    fixed (char* ps = s)
    {
        for (int i = 0; i < newContents.Length;   i)
        {
            ps[i] = newContents[i];
        }
    }
}
  

Вы можете быть удивлены, узнав, что, хотя строка ‘a’ является измененной, вывод будет:

b=raboof

В этой ситуации хотелось бы написать:

 string a = "foobar";
string b = new String(a);
Mutate(a, "raboof");
Console.WriteLine("b={0}", b);
  

И ожидайте увидеть вывод, подобный:

b = foobar

Но вы не можете, потому что это не является частью реализации System.Строка.

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

Комментарии:

1. Даже если вы не используете небезопасный код, есть некоторые ситуации, в которых может быть полезно иметь строку, которая, как известно, не является ссылочной — равной любой другой строке, которая может существовать где угодно во вселенной — для проверки поведения кода интернирования строки, если ничего другого. Как уже было сказано, тот факт, что повторные вызовы для new String(' ', 0) получения одного и того же экземпляра означают, что неясно, что повторные вызовы new String("Fred") не будут делать то же самое.

2. Достаточно верно в отношении гипотетического поведения, которое будет иметь конструктор String (string). Тем больше причин написать свой собственный небезопасный метод клонирования. 🙂

3. Лично я так думаю . NET должен был либо иметь конструкторы типа класса, которые всегда выдают новые экземпляры объектов, либо заставлять их вызывать фабричные методы, которые имели бы возможность возвращать кэшированные экземпляры. Я могу оценить, что в большинстве случаев совместное использование экземпляров строк нулевой длины было бы неплохо, но правильным способом справиться с этим было бы иметь String.Repeat(char,int) перегрузку, спецификация которой указывала, что можно свободно использовать экземпляры string для любых комбинаций параметров параметров, которые казались целесообразными.

Ответ №6:

Конструктор, который вы пытаетесь использовать, принимает…

Указатель на массив символов Unicode, завершающийся нулем

…вместо строки.

(См http://msdn.microsoft.com/en-us/library/aa331864 (v= VS.71).aspx)

Ответ №7:

Просто чтобы сделать видимым комментарий Эрика Липпертса:

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

Ответ №8:

С моей стороны, я получаю это:

Лучший перегруженный метод соответствует `string.String(char[])’ имеет некоторые недопустимые аргументы

Возможно, вы ввели «char *» вместо «char []» при публикации.

Возможно, это связано с нашим историческим пониманием литералов. До C # значение, заключенное в кавычки (например, «astringvalue»), можно было рассматривать как указатель на символ. Однако в C # «astringvalue» — это просто объект типа string class . Оператор:

 String s= new String("Hello World");
  

подразумевало бы создание объекта типа String class и вызов его конструктора. Компилятор проверяет список конструкторов, доступных для класса string . Он не может найти ни одного конструктора, который мог бы принять объект string («Hello world»). Как и в любой другой ситуации, компилятор делает наилучшее предположение о том, какой метод является «ближайшим» из списка перегруженных методов — в этом случае предполагается, что строковое значение «Hello world» ближе всего к массиву символов (char []) — и сообщает вам, что ваш «Hello world» (переданное вами значение) является недопустимым значением для «char []».

Ответ №9:

На мой взгляд, основное различие заключается в «Передаче по ссылке» и «передаче по значению» в .NET и JAVA.

Что приводит к шаблону проектирования в Java по причине, которая может быть

Конструктор для копирования объекта того же класса.

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

‘String test = txtName .Текст;’

Это мое понимание .net и java.

Надеюсь, я смог дать правильные рассуждения.

Спасибо и с уважением

Жесткая ошибка

Комментарии:

1. НЕТ, НЕТ, НЕТ. Вся передача (без out и ref ) в C # является вызовом по значению (по ссылке) . Для ссылочных типов это лучше описать как совместное использование вызовов по объектам . Вызов по ссылке не связан, как и «Конструктор копирования». Неизменяемые объекты [обычно] не нуждаются в «Конструкторе копирования» — строки в Java и C # неизменяемы.

2. C имеет очень точное определение конструктора копирования , которое используется даже для неизменяемых типов в C — но это C , а не C # или Java.

3. Сборка мусора — большая часть того, почему C должен создавать копии, когда C # и Java этого не делают. В C , даже если объект имеет неизменяемое содержимое , его может потребоваться клонировать, поскольку у копии другое время жизни. В системе GC можно просто бесконечно продлевать срок службы оригинала до тех пор, пока он все еще необходим.