2017-02-22 33 views
3

Похоже, хорошее конструктивное решение состоит в том, что класс System.Object и, следовательно, все классы в .NET предоставляют метод ToString(), который, что неудивительно, возвращает строковое представление объекта. Кроме того, в C# этот метод реализуется для собственных типов, чтобы они хорошо интегрировались с системой типов.Почему нет обратного объекта.ToString()?

Это часто пригодится, когда требуется взаимодействие с пользователем. Например, объекты могут непосредственно храниться в виджетах GUI, таких как списки, и автоматически отображаются в виде текста.

Какое обоснование в плане языка не предусматривает аналогичный общий метод object.FromString(string)?

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

  • разбора может потерпеть неудачу, в то время как преобразование в строку всегда возможно.

    • Ну, это не мешает Parse() методы из существующих, не так ли? Если обработка исключений считается нежелательной конструкцией, можно все же определить метод TryParse(), стандартная реализация которого для System.Object просто возвращает значение false, но переопределяется для конкретных типов, где это имеет смысл (например, типы, в которых этот метод существует сегодня).

    • В качестве альтернативы, как минимум, было бы неплохо иметь IParseable интерфейс, который объявляет ParseMe() или TryParse() метод, вдоль линий ICloneable.

  • Комментарий от Tim Schmelter-х "Ролл свой собственный": Это работает, конечно. Но я не могу написать общий код для собственных типов или, скажем, IPAddress, если я должен проанализировать значения; вместо этого мне приходится прибегать к интроспекции типа или писать обертки, которые реализуют самоопределяемый интерфейс, который либо является недружественным, либо утомительным, либо подверженным ошибкам.

  • Комментарий от Damien: Интерфейс может только объявить не-статические функции по причинам, обсуждаемым here Эриком Липпертом. Это очень веское возражение. Статический метод TryParse() не может быть указан в интерфейсе. Виртуальный метод ParseMe(string), хотя нужен фиктивный объект, который в лучшем случае является kludge и в худшем случае (с RAII). Я почти подозреваю, что это основная причина такого интерфейса не существует. Вместо этого существует сложная структура преобразования типов, одна из альтернатив, упомянутых в качестве решений для «оксимерного» «статического интерфейса».

Но даже учитывая возражения в списке, отсутствие общего синтаксического анализа объекта в системе типа или языке, как представляется мне, как неудобная асимметрия, учитывая, что общий ToString() метода существует и является чрезвычайно полезным.

Было ли это когда-либо обсуждалось во время разработки языка/CLR?

+1

Для того, чтобы 'IParsable' работал, вам нужно сначала получить экземпляр. Если проблема заключается в том, чтобы «превратить эту строку в экземпляр X», вам кажется несколько неудобным, что вам сначала нужно получить какой-либо другой экземпляр X, чтобы вы могли называть его «FromString()». –

+0

Что именно было бы по умолчанию для этого, просто выбросить исключение? – juharr

+1

Вы можете преобразовать только несколько типов из строки в 'OtherType', но вы можете преобразовать все типы в' string'. Какая польза от этого? Вы всегда можете предоставить конструктор или фабричный метод (например, с шаблоном TryParse), который создает экземпляр из строки, если это необходимо и возможно. –

ответ

10

Почему нет обратных к object.ToString()?

Поскольку object должен держать голую минимальную функциональность, необходимую каждый объекта. Сравнение равенства и преобразования в строку (по многим причинам) - два из них. Преобразование - нет. Проблема в том, как он должен преобразовываться? Использование JSON? Binary? XML? Что-то другое? Не существует единого способа конвертировать из строки. Следовательно, это излишне раздувало класс object.

В качестве альтернативы, как минимум, было бы неплохо иметь IParseable интерфейсу

Там есть: IXmlSerializable, например, или один из многих альтернатив.

+2

IConvertible ["конвертировать (s) значение ссылочной реализации или типа значения ** в общий тип среды выполнения." **] (https://msdn.microsoft.com/en-us/library/system.convertible (v = vs.110) .aspx) Это противоположный случай использования: my * source type * - это тип среды CLR, а именно 'string'; мой * целевой тип *, напротив, является настраиваемым типом или фактически IPAddress. Все типы, которые я хочу проанализировать, чтобы разоблачить метод 'Parse', но язык не имеет средств для выражения этой общности. –

+0

Вы правы. Удалит это. –

13

Похоже, хорошее дизайнерское решение, что класс System.Object, и, следовательно, все классы в .NET обеспечивают метод ToString()

Может вам. Мне всегда казалось, что это действительно плохая идея.

который, неудивительно, возвращает строковое представление объекта.

Это правда? Для подавляющего большинства типов ToString возвращает имя типа. Как это строковое представление объекта?

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

Поскольку у ToString нет четкого контракта, практически нет ничего, что можно безопасно использовать для него, за исключением вывода отладчика. Я имею в виду действительно, подумайте об этом: когда вы в последний раз звонили ToStringна объект в код? У меня никогда не было.

Лучшая конструкция, поэтому были бы методы static string ToString<T>(T) и static string ToString(object) на классе Debug. Тогда они могли бы получить «нуль», если объект был нулевым, или сделали некоторое отражение на T, чтобы определить, есть ли визуализатор отладчика для этого объекта и т. Д.

Итак, теперь рассмотрим достоинства вашего фактического предложения, которое является общим требованием, чтобы все объекты были десериализуемыми из строки. Обратите внимание: сначала это явно не обратная операция ToString. Подавляющее большинство реализаций ToString не производят ничего, что вы могли бы использовать даже в теории для воссоздания объекта.

Итак, ваше предложение о том, что ToString и FromString являются обратными? Это значит, что каждый объект не просто «представлен» как строка, а то, что на самом деле это с сечением сериализуемого номера.

Давайте рассмотрим пример. У меня есть объект, представляющий таблицу базы данных. Does ToString на этой таблице теперь сериализует все содержимое таблицы? Does FromString десериализует его? Предположим, что объект фактически является оберткой вокруг соединения, которое извлекает таблицу по требованию; что мы сериализуем и десериализуем тогда?Если для подключения нужен мой пароль, он вводит мой пароль в строку?

Предположим, у меня есть объект, который ссылается на другой объект, так что я не могу десериализовать первый объект, не имея второго в руке. Репликация сериализации по объектам? Что относительно объектов, где граф ссылок содержит петли; как мы с ними справляемся?

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

Даже если предположить, что мы хотели это сделать, почему string из всех вещей? Строки - это ужасный тип данных сериализации. Они не могут легко хранить двоичные данные, они должны быть полностью присутствующими в памяти сразу, они не могут превышать миллиард символов, они не имеют структуры для них и т. Д. То, что вы действительно хотите для сериализации, - это структурированная двоичная система хранения.

Но даже учитывая возражения в списке, отсутствие общего синтаксического анализа объекта в системе типа или языке, как представляется мне, как неудобная асимметрия, учитывая, что общий метод ToString() существует и является чрезвычайно полезным.

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

Было ли это когда-либо обсуждалось во время языка/дизайна CLR?

Был ли ToString когда-либо обсуждался? Очевидно, это было; он был реализован. Была ли когда-либо обсуждалась обобщенная библиотека сериализации? Очевидно, это было; он был реализован. Я не уверен, что вы здесь делаете.

+0

Спасибо за подробный ответ. (1) Re "' ToString() 'в основном полезно для отладки": я также полагаюсь на него в моих графических интерфейсах (например, объекты в списках, datagrids). (2) Ваши возражения относительно семантики/сериализации в оба конца: точка взята. Но я не предлагал этого в общем случае. (То есть, object.Parse() всегда терпит неудачу.) Существует спектр типов, хотя - например. все родные типы, которые имеют текстовое представление с обратным путешествием. И, как и в случае с «ICloneable», против которого были сделаны возражения в отношении неконтрактного: это зависит от пользователя, чтобы определить его с помощью желаемой семантики. –

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

  • Нет связанных вопросов^_^