Почему существует object.ToString()?

Разве интерфейс IStringable не намного элегантнее и изящнее?

Кому нужен этот объект Type.FullName, возвращенный нам?

EDIT: все продолжают спрашивать, почему я думаю, что это более элегантно..

Ну, просто так, вместо IComparable у объекта будет метод CompareTo, который по умолчанию выдает исключение или возвращает 0.

Есть объекты, которые не могут и не должны описываться строкой. объект мог бы точно так же вернуть string.Empty. Type.FullName это просто произвольный выбор..

А для таких методов, как Console.Write(object), я думаю, должно быть: Write(IStringable).

Однако, если вы используете WriteLine для чего-либо, кроме строк (или чего-то, что его ToString очевидно, например, чисел), мне кажется, что это только для режима отладки.

Кстати, как мне вам всем прокомментировать? Ничего, что я опубликую ответ?


person Letterman    schedule 13.10.2009    source источник
comment
Итак, в чем преимущество, которое вы получите, заменив object.ToString на IStringable { string ToString(); }?   -  person Juliet    schedule 13.10.2009
comment
@Почему существует object.ToString()? -- почти уверен, что все объекты в .NET поддерживают .ToString() по дизайну. У Microsoft был способ их безумия.   -  person Hardryv    schedule 13.10.2009
comment
+1 и Аминь и не менее 15 символов.   -  person csharptest.net    schedule 13.10.2009
comment
Чтобы прокомментировать для всех нас, либо добавьте комментарий к своему вопросу, либо добавьте четко обозначенное обновление к своему вопросу.   -  person StriplingWarrior    schedule 13.10.2009
comment
Я просто предполагаю, что это пережиток Java. Однако Java использует метод toString() всякий раз, когда вы используете оператор + для объектов. В Java это может сойти с рук, потому что она не поддерживает перегрузку операторов.   -  person Powerlord    schedule 13.10.2009
comment
@Bemrose: Это действительно с Java, см. мою небольшую историю ниже (или спросите у Хейлсберга). Но если вы спросите, почему существует ToString(), вы также должны спросить, почему существует GetType(), у нас уже есть оператор typeof. И почему существует Equal(), у нас уже есть оператор ==. Были очень внятные причины для наличия ToString (и других) в базе: раньше или позже нужно отображать так или иначе. Таким образом, каждому объекту просто требуется ToString(). В качестве бонуса: вы всегда можете создать IStringable и использовать его вместо него! А, кстати, зачем вообще существует C#?   -  person Abel    schedule 14.10.2009
comment
@Abel Цитирование необходимо для Были очень разные причины наличия ToString (и других) в базе   -  person Emperor Orionii    schedule 12.01.2013
comment
@EmperorOrionii: я думаю, что мой ответ в этой теме (более трех лет назад) дает некоторые из этих причин. Некоторое другое обсуждение находится в Прикладном программировании Microsoft .NET Framework Рихтера. См. также его обсуждение в этой книге о .Equals, в которой были подобные обсуждения.   -  person Abel    schedule 13.01.2013
comment
IMO кажется забавным, что язык должен предоставлять метод только для отладки в каждом object; что плохого в том, чтобы вводить имя объекта и иметь расширяемый список свойств? Гипотетически Visual Studio (не C#) можно было бы запрограммировать на показ значений свойств/переменных встроенных типов, таких как string и int, из коробки, а пользовательские типы просто должны были бы полагаться на DebuggerDisplayAttribute (хотя да, атрибут display не был с момента появления .NET).   -  person jrh    schedule 10.01.2018


Ответы (12)


Есть три виртуальных метода, которые ИМХО никогда не следовало добавлять в System.Object...

  • Нанизывать()
  • ПолучитьHashCode()
  • Равно()

Все это можно было бы реализовать, как вы предлагаете, с интерфейсом. Если бы они так поступили, я думаю, нам было бы намного лучше. Так почему это проблема? Давайте просто сосредоточимся на ToString():

  1. Если ожидается, что ToString() будет реализован кем-то, использующим ToString() и отображающим результаты, у вас есть неявный контракт, который компилятор не может обеспечить. Вы предполагаете, что ToString() перегружена, но нет способа заставить это быть так.
  2. С IStringable вам нужно будет только добавить это к вашему общему ограничению типа или получить от него свой интерфейс, чтобы потребовать его использования при реализации объектов.
  3. Если преимущество, которое вы обнаружите в перегрузке ToString(), предназначено для отладчика, вы должны начать использовать [System.Diagnostics.DebuggerDisplayAttribute].
  4. Что касается необходимости этой реализации для преобразования объектов в строки через String.Format() и/или Console.WriteLine, они могли бы отложить до System.Convert.ToString(object) и проверить что-то вроде «IStringable», переключившись на имя типа, если оно не реализовано.
  5. Как отмечает Кристофер Эстеп, это зависит от культуры.

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

Примечание. Если вы намерены зависеть от перегруженного поведения ToString(), я бы посоветовал вам продолжить и определить свой интерфейс IStringable. К сожалению, вам придется выбрать другое имя для метода, если вы действительно хотите его использовать.

больше

Мы с коллегами как раз говорили на эту тему. Я думаю, что еще одна большая проблема с ToString() — это ответ на вопрос «для чего он используется?». Это отображаемый текст? Текст сериализации? Отладка текста? Полное имя типа?

person csharptest.net    schedule 13.10.2009
comment
Вы действительно хорошо ответили на вопрос и принесли много хороших баллов, +1! - person Meta-Knight; 13.10.2009
comment
+1. По пункту 5 я бы сказал, что ситуация хуже, чем вы написали. ToString часто зависит от культуры, но я не думаю, что вы можете предположить, что это всегда так. Некоторый сторонний объект может использовать инвариантный язык и региональные параметры. Вы просто не можете полагаться на ToString ни для чего, кроме отладки или регистрации. - person MarkJ; 13.10.2009
comment
ситуация хуже, чем вы написали, несомненно. :) - person csharptest.net; 13.10.2009
comment
Без метода equals вам не было бы гарантировано автоматическое использование метода equals при проверке строк. GetHashCode позволяет очень быстро сравнивать объекты внутри других структур (это хорошо). ToString значительно упрощает отображение объекта в отладчике. - person monksy; 13.10.2009
comment
Слишком много интерфейсов для фреймворков Java/Apache. В методах, которые вы указываете, больше пользы, чем боли. - person mimetnet; 13.10.2009
comment
@mimetnet Java также имеет toString(), поэтому я не уверен, о каком сравнении вы говорите. Что касается других языков в целом, у меня нет ToString() в C++, и я тоже не скучаю по нему. Я признаю, что мне не хватает атрибута [DebuggerDisplay] в неуправляемом коде :) - person csharptest.net; 14.10.2009
comment
@csharptest.net, если объект является строкой и вы вызываете метод .ToString(). Есть ли последствия для производительности, например, создает ли он новую строку или знает, что это уже строка? - person MIKE; 28.04.2020

Наличие Object.ToString делает возможными такие API, как Console.WriteLine.

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

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

person JaredPar    schedule 13.10.2009
comment
Это особенно полезно при проверке объектов в отладчике или генерации исключений во время выполнения, чтобы иметь возможность создавать текстовое представление объекта. - person LBushkin; 13.10.2009
comment
так почему Console.WriteLine не определяется как: WriteLine(Istringable)? - person Letterman; 13.10.2009
comment
Интересно, почему они заставили это работать для Console.WriteLine, но не для Messagebox.Show, как они сделали для VB.NET? - person Mez; 13.10.2009

Я предполагаю, что он существует, потому что это чрезвычайно удобно иметь на всех объектах и ​​не требует дополнительных усилий для использования. Как вы думаете, почему IStringable будет более элегантно?

person Greg D    schedule 13.10.2009
comment
потому что есть вещи, которые определенно можно описать как струны, а есть вещи, которые таковыми не являются. это похоже на то, что вместо IComperable объект будет иметь CompareTo, который по умолчанию выдает исключение. - person Letterman; 13.10.2009

Нисколько.

Его не нужно реализовывать, и он возвращает результаты, зависящие от языка и региональных параметров.

Этот метод возвращает удобочитаемую строку с учетом языка и региональных параметров. Например, для экземпляра класса Double, значение которого равно нулю, реализация Double..::.ToString может вернуть "0,00" или "0,00" в зависимости от текущего языка и региональных параметров пользовательского интерфейса.

Кроме того, хотя он поставляется со своей собственной реализацией, его можно переопределить, что часто и происходит.

person Chris E    schedule 13.10.2009

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

person Otávio Décio    schedule 13.10.2009

«Строковое» представление полезно во многих сценариях, и разработчики библиотеки, вероятно, думали, что ToString() более прямолинеен.

person Larsenal    schedule 13.10.2009

С IStringable вам придется выполнить дополнительную проверку/приведение, чтобы увидеть, можете ли вы вывести объект в строковом формате. Это слишком большой удар по производительности для такой общей операции, которая в любом случае должна быть хорошей вещью для 99,99% всех объектов.

person Xerion    schedule 13.10.2009
comment
@itay ... По сути, вы поддерживаете TryCast каждый раз, когда хотите вывести значение объекта. Во всем этом приведении нет необходимости, потому что с .TOString() экземпляр гарантированно выдаст результат. - person StingyJack; 13.10.2009
comment
Почему ты так горячишься за отладку во всех своих постах и ​​комментариях? Да, это помогает при отладке. Да, это помогает в самоанализе. Отладка составляет примерно 70-80% нашего времени программирования. Даже если бы я согласился с вами, я бы определенно проголосовал за это. Альтернативой является то, что объект может быть представлен только своим адресом (как в C++). К счастью, ToString() и его многочисленные помощники экономят не только на отладке, но и просто упрощают (частично) написание кода: Console.Write, String.Format, ToString(LocaleHere) и т. д. - person Abel; 14.10.2009
comment
(вы == Itay, а не StingyJack, извините, если моя формулировка неясна) - person Abel; 14.10.2009

Мммм, значит, его можно переопределить в производных классах?

person leppie    schedule 13.10.2009

Структуры и объекты имеют член ToString() для облегчения отладки.

Самый простой пример этого можно увидеть с помощью Console.WriteLine, который получает весь список типов, включая объект, но также получает params object[] args. Поскольку Console часто является слоем поверх TextWriter, эти операторы также полезны (иногда) при записи в файлы и другие потоки (сокеты).

Он также иллюстрирует простой объектно-ориентированный дизайн, который показывает, что интерфейсы не должны создаваться только потому, что вы можете это сделать.

person mimetnet    schedule 13.10.2009
comment
Вы когда-нибудь слышали об DebuggerDisplayAttribute? - person Meta-Knight; 13.10.2009
comment
Я не фанат отладчиков ни для чего, кроме seg-faults в C/C++. Я лично чувствую, что они больше вредят вашим долгосрочным способностям, чем могут помочь с краткосрочным исправлением. - person mimetnet; 13.10.2009
comment
DebuggerDisplayAttribute не добавлялся до версии .Net 2.0. - person Preston McCormick; 16.05.2012
comment
С чисто проектной точки зрения ToString() не имеет явного отношения к отладчику (или, если вам нужен менее теоретический пример, в кодовой базе, над которой я работаю, последняя группа программистов предполагала, что ToString() это то, что они могут свободно делать трудоемкая операция на). С точки зрения неотладки, я стал не любить классы, которые принимают любые object и автоматически предполагают, что любое переопределение ToString() будет правильным форматом, во всяком случае, я хочу, чтобы компилятор выдал ошибку, если он просто собирается распечатать полное имя типа вместо полезных данных. - person jrh; 08.01.2018
comment
... Также ToString может означать почти что угодно: полное имя типа (поведение по умолчанию), отладочный текст (обычное использование), локализованный отображаемый текст (возможно, наиболее практичное поведение), двоичные данные объекта, преобразованные в строку Base64, данные объекта в формате csv и т. д. и т. д. — и я видел все это в различных кодовых базах. Конечно, вы можете добавить комментарий, говорящий, что именно он делает, и MS может задокументировать его типичное использование, но ни один из них не был бы необходим, если бы .NET не предлагал этот метод для начала как то, что есть у всех объектов. - person jrh; 08.01.2018

Мой новый базовый класс:

class Object : global::System.Object
{
    [Obsolete("Do not use ToString()", true)]
    public sealed override string ToString()
    {
        return base.ToString();
    }

    [Obsolete("Do not use Equals(object)", true)]
    public sealed override bool Equals(object obj)
    {
        return base.Equals(this, obj);
    }

    [Obsolete("Do not use GetHashCode()", true)]
    public sealed override int GetHashCode()
    {
        return base.GetHashCode();
    }
}
person csharptest.net    schedule 13.10.2009
comment
Какую, скажи на милость, проблему ты собираешься решить? - person Robert Rossney; 13.10.2009
comment
Все эти методы в производных реализациях теперь имеют надежное поведение. Теперь я могу знать, для чего используется ToString() и что означает Equals. - person csharptest.net; 13.10.2009
comment
и вы ограничиваете возможность наследования от MarhalByRefObject, Page, Form или других важных классов, когда вам это нужно. К сожалению, в C# не поддерживается множественное наследование, и изменение общего базового класса невозможно. Хорошая идея, но, к сожалению, не может быть использована на практике. - person Abel; 14.10.2009
comment
@Abel LOL, достаточно верно для MBR и т. Д. Очевидно, я немного саркастичен в отношении вышеуказанного класса, чтобы преувеличить значение. - person csharptest.net; 14.10.2009
comment
@csharptest, ага, рад, что ты это сказал, ты меня на мгновение забеспокоил, лол! - person Abel; 14.10.2009

Действительно, мало смысла возвращать вам Type.FullName, но было бы еще меньше пользы, если бы возвращалась пустая строка или ноль. Вы спрашиваете, почему он существует. На этот вопрос не так-то просто ответить, и он является предметом многочисленных дискуссий в течение многих лет. Более десяти лет назад несколько новых языков решили, что было бы удобно неявно приводить объект к строке, когда это необходимо. К таким языкам относятся Perl, PHP и JavaScript, но ни один из них не следует полностью парадигме объектной ориентации.

подходы

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

  • Используйте множественное наследование, просто наследуйте от String, и вы можете быть преобразованы в строку
  • Одиночное наследование: добавьте ToString в базовый класс как виртуальный метод
  • Либо: сделать оператор приведения или конструктор копирования перегружаемым для строк

Возможно, вы спросите себя, зачем вам нужен ToString или аналогичный. в первую очередь? Как уже отмечали некоторые другие: ToString необходим для самоанализа (он вызывается, когда вы наводите указатель мыши на любой экземпляр объекта), и отладчик тоже его покажет. Как программист, вы знаете, что для любого ненулевого объекта вы всегда можете безопасно вызвать ToString. Не нужен литой, не нужна конверсия.

Считается хорошей практикой программирования всегда реализовывать ToString в ваших собственных объектах со значимым значением из ваших сохраняемых свойств. Перегрузки могут помочь, если вам нужны разные типы представления вашего класса.

Больше истории

Если вы углубитесь в историю, мы увидим, что SmallTalk использует более широкий подход. Базовый объект имеет гораздо больше методов, включая printString, printOn и т.д.

Небольшое десятилетие спустя, когда Бертран Мейер написал свою знаменательную книгу «Конструкция объектно-ориентированного программного обеспечения», он предложил использовать довольно широкий базовый класс GENERAL. Он включает такие методы, как print, print_line и tagged_out, причем последний показывает все свойства объекта, но не ToString по умолчанию. Но он предполагает, что "второй базовый объект ANY, от которого происходят все пользовательские объекты, может быть расширен", что похоже на подход прототипа, который мы теперь знаем из JavaScript.

В C++, единственном языке множественного наследования, все еще широко используемом, не существует общего предка для всех классов. Это может быть лучший язык-кандидат для использования вашего собственного подхода, то есть используйте IStringable. Но у C++ есть и другие способы: вы можете перегрузить оператор приведения и конструктор копирования, чтобы реализовать возможность строк. На практике необходимость явно указывать реализацию to-string (как вы предлагаете с IStringable) становится довольно громоздкой. Программисты на С++ это знают.

В Java мы находим первое появление toString для основного языка. К сожалению, в Java есть два основных типа: объекты и типы значений. Типы значений не имеют метода toString, вместо этого вам нужно использовать Integer.toString или привести к аналогу объекта. Это оказалось очень громоздким на протяжении многих лет, но программисты Java (включая меня) научились с этим жить.

Затем появился C# (я пропустил несколько языков, не хочу делать его слишком длинным), который изначально задумывался как язык отображения для платформы .NET, но оказался очень популярным после первоначального скептицизма. Разработчики C# (Андерс Хейлсберг и др.) смотрели в основном на C++ и Java и пытались взять лучшее из обоих миров. Тип значения остался, но был введен бокс. Это позволило неявно наследовать типы значений от Object. Добавление ToString аналога Java было всего лишь небольшим шагом и было сделано для облегчения перехода от мира Java, но к настоящему времени оно показало свои неоценимые достоинства.

странность

Хотя вы прямо не спрашиваете об этом, но почему следующее должно потерпеть неудачу?

object o = null;
Console.WriteLine(o.ToString());

и пока вы думаете об этом, учтите следующее, что не подводит:

public static string MakeString(this object o)
{ return o == null ? "null" : o.ToString();  }

// elsewhere:
object o = null;
Console.WriteLine(o.MakeString());

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

У Eiffel в то время был специальный класс NIL, который представлял ничто, но все же имел все методы базового класса. Иногда мне хотелось, чтобы C# или Java вообще отказались от null, как это сделал Бертран Мейер.

Вывод

Широкий подход классических языков, таких как Eiffel и Smalltalk, был заменен очень узким подходом. В Java по-прежнему много методов для Object, а в C# — всего несколько. Это, конечно, хорошо для реализации. Хранение ToString в пакете просто делает программирование чистым и в то же время понятным, а поскольку это virtual, вы можете (и должны!) всегда переопределять его, что сделает ваш код более понятным.

-- Абель --

EDIT: автор вопроса отредактировал вопрос и сравнил его с IComparable, то же самое, вероятно, верно и для ICloneable. Это очень хорошее замечание, и часто считается, что IComparable следовало бы включить в Object. В соответствии с Java, C# имеет Equals, а не IComparable, но в отличие от Java C# не имеет ICloneable (в Java есть clone()).

Вы также заявляете, что это удобно только для отладки. Что ж, учтите это везде, где вам нужно получить строковую версию чего-либо (надуманно, без дополнительных методов, без String.Format, но вы поняли):

CarInfo car = new CarInfo();
BikeInfo bike = new BikeInfo();
string someInfoText = "Car " +
   (car is IStringable) ? ((IStringable) car).ToString() : "none") +
   ", Bike " + 
   (bike is IStringable) ? ((IStringable) bike).ToString() : "none");

и сравните это с этим. Вы должны выбрать то, что вам проще:

CarInfo car = new CarInfo();
BikeInfo bike = new BikeInfo();
string someInfoText = "Car " + car.ToString() + ", Bike " + bike.ToString();

Помните, что языки предназначены для того, чтобы делать вещи яснее и проще. Многие части языка (LINQ, методы расширения, ToString(), оператор ??) созданы для удобства. Ничего из этого не является необходимостью, но мы, конечно же, рады, что они у нас есть. Только когда мы знаем, как их правильно использовать, мы также находим истинную ценность функции (или нет).

person Abel    schedule 13.10.2009
comment
хм? поэтому с ToString объекта вы получите что-то вроде: Car OuterNameSpace.InternalNamespace.CarInfo, Bike OuterNameSpace.InternalNamespace.BikeInfo. да, действительно удобно для пользователя.. в любом случае, вы упускаете из виду, где, кроме отладки, вам нужно будет ли вам нужно преобразовать что-то в строку, не зная, поддерживает ли это это или нет? а если нет, что вы покажете своему пользователю? - person Letterman; 14.10.2009
comment
Нет, это распространенное заблуждение. ToString обычно переопределяется, это общий принцип проектирования для сериализуемых объектов (извините за автомобили и велосипеды, считайте их обычными POCO или подобными), и даже несериализуемый объект должен переопределять ToString. Когда вы переопределяете его, вызывается ToString объекта your. Вот почему это в первую очередь виртуальный метод. Извините, если мой пример не был ясен. Есть несколько ситуаций, когда вам не нужны ToString() или ToString(params), но я не могу судить о вашей ситуации. Без него не должно быть POCO. Это просто экономит время и добавляет ясности. - person Abel; 14.10.2009
comment
Кстати, что вы имели в виду, цитата: Bike OuterNameSpace.InternalNamespace.BikeInfo, поскольку нет необходимости указывать пространства имен. Вы импортируете это с помощью директив using, как и в других языках. - person Abel; 14.10.2009
comment
@Abel: это было довольно давно, и на самом деле мне потребовалось некоторое время, чтобы понять, что я имел в виду. Что касается вашего последнего примера, как вы можете не знать, что конкретный тип реализует IStringable или нет? но даже если вы получаете экземпляр в качестве аргумента и не знаете, что это такое, ВСЕ ЕЩЕ не имеет смысла делать то, что вы сделали, потому что, если он не переопределяет ToString, вы получите полное имя типа, которое конечно, не то, что нужно отправить пользователю ... и вы не можете ГАРАНТИРОВАТЬ, что это переопределено, что важно. Однако - person Letterman; 07.02.2011
comment
и однако, если вы хотите получить объект, который может быть представлен в виде текста, просто получите IStringable. я не понимаю, как это становится настолько сложным...... object.ToString() для всего, а IStringable.ToString() только для stringables. конец истории. я все еще говорю, где, когда-либо, помимо отладки, вы захотите что-то написать, не зная, в какой погоде это реализовано или нет.... и на практике МНОГИЕ объекты не реализуют ToString - person Letterman; 07.02.2011
comment
@Itay: Это действительно давно. Но если вы используете интерфейс, который определяет уже существующий метод, интерфейс должен быть реализован явно, а приведение необходимо для вызова правильного метода. Но просто назвав его отличным от ToString(), вы, конечно, избавитесь от этого уродливого обходного пути. Но, перечитывая мой ответ, я не думаю, что полностью понял суть вашего вопроса;) - person Abel; 17.02.2011
comment
Я думаю, может быть полезно увидеть полное имя типа. Например, когда у вас есть только ссылка на интерфейс... наведите указатель мыши на него в отладчике, и обычно вы можете увидеть, что это за конкретный тип. - person Preston McCormick; 16.05.2012
comment
Использование MemberwiseClone в качестве защищенной функции Object, которая по умолчанию доступна во всех подклассах, было ошибкой (в отличие от ToString()). Было бы лучше иметь магический Cloneable, производный от Object, который включал защищенный виртуальный метод BaseClone, и иметь вещи, которые должны поддерживать любой тип клонирования, производные от него, или же иметь некую форму опциональных защищенных членов, чтобы если класс не запрашивает их, его подклассы тоже не могут. Есть много классов, в которых подкласс не может законно использовать MemberwiseClone. - person supercat; 19.12.2013
comment
Я согласен с вами, что было бы полезно, если бы некоторые методы объекта (например, Equals) были нулевыми невиртуальными оболочками виртуальных функций. На самом деле мне бы хотелось, чтобы String был типом значения, который - как деталь реализации - инкапсулировал бы ссылку на какую-то последовательность символов, хранящуюся в другом месте [это может быть Char[], но возможны и другие реализации] . Между прочим, я думаю, что разрешение бокса на Object было ошибкой; должен был быть отдельный тип места хранения для переменной, для которой разрешен бокс. - person supercat; 19.12.2013
comment
Развернув эту концепцию немного дальше, я бы разрешил упаковывать не только типы значений, но и любой тип. По сути, T в штучной упаковке был бы похож на T[], но без каких-либо размеров. Точно так же, как Animal[1], который содержит ссылку на SiameseCat, отличается от Cat[1], который содержит ссылку на тот же экземпляр, так и я хотел бы видеть типы блоков. Фикция о том, что типы значений и типы классов все Object, ИМХО больше сбивает с толку, чем помогает. - person supercat; 19.12.2013

Я хотел бы добавить пару мыслей о том, почему определение класса .NET System.Object имеет метод или функцию-член ToString() в дополнение к предыдущим сообщениям об отладке.

Поскольку .NET Common Language Runtime (CLR) или Execution Runtime поддерживает Reflection, возможность создания экземпляра объекта с учетом строкового представления типа класса кажется важной и фундаментальной. И если я не ошибаюсь, все ссылочные значения в CLR являются производными от System.Object, наличие метода ToString() в классе обеспечивает его доступность и использование через Reflection. Определение и реализация интерфейса наподобие IStringable не является обязательным или обязательным при определении класса в .NET и не гарантирует возможности динамического создания нового экземпляра после запроса сборки на предмет поддерживаемых типов классов.

Поскольку более продвинутые функции .NET, доступные в средах выполнения 2.0, 3.0 и 3.5, такие как Generics и LINQ, основаны на отражении и динамическом создании экземпляров, не говоря уже о поддержке .NET Dynamic Language Runtime (DLR), которая позволяет реализовывать сценарии .NET. В языках, таких как Ruby и Python, возможность идентифицировать и создавать экземпляр по строковому типу кажется существенной и незаменимой функцией, которую необходимо иметь во всех определениях классов.

Короче говоря, если мы не можем определить и назвать конкретный класс, который хотим создать, как мы можем его создать? Кажется, имеет смысл полагаться на метод ToString(), который имеет поведение базового класса, возвращая тип класса в виде «читаемой человеком» строки.

Возможно, обзор статей и книг Джеффри Риктера и Дона Бокса по проектированию и архитектуре .NET Framework также поможет лучше понять эту тему.

person ClockEndGooner    schedule 13.10.2009
comment
1. Короче говоря, если мы не можем идентифицировать и назвать конкретный класс, который мы хотим создать, как мы можем его создать? Вы можете использовать Object.GetType().FullName. 2. ... для создания экземпляра объекта с учетом строкового представления типа класса... Это просто проблема с ToString(), он не имеет смысла, потому что он виртуальный. Это может быть что угодно или null, и он не заменяет вызов Object.GetType().FullName. - person csharptest.net; 13.10.2009