Являются ли в C# термины «примитивный» и «литеральный» взаимозаменяемыми?
-
20-09-2019 - |
Вопрос
Сегодняшнее обсуждение заставило меня задаться вопросом, правильно ли я понимаю примитивы и литералы.
Насколько я понимаю, литеральный тип — это тип, которому может быть присвоено значение с использованием нотации, понятной как человеку, так и компилятору без конкретных объявлений типа:
var firstName = "John"; // "John" is literal
var firstName = (string)"John"; // *if* the compiler didn't understand that "John"
// was a literal representation of a string then I
// would have to direct it as such
Насколько я понимаю примитивы, это, по сути, элементарные типы данных, которые может понять компилятор, например int:
int age = 25;
... литерал может быть не примитивным, как, например, поддержка VB9 литералов XML.Нереальным примером может быть присвоение System.Drawing.Point литералов:
Point somePoint = 2,2; // both X and Y are primitive values, however Point is a
// composite value comprised of two primitive values
Наконец (и именно этот вопрос, в свою очередь, побудил меня задать вышеупомянутые вопросы):Насколько я понимаю, независимо от того, является ли тип примитивным или буквальным, нет прямой зависимости от того, является ли он типом значения или ссылкой.
Например, System.String — это ссылочный тип, поддерживающий литералы.Пользовательские структуры — это составные типы значений, которые не поддерживают литералы.
Верно ли мое понимание (если не объяснение) по большей части?
Обновлять: Спасибо за интересную информацию и общение!Всем, кто это обнаружит, обязательно прочитайте комментарии, а также ответы, там есть несколько отличных разъяснений, а также несколько интересных примечаний.
кстати:это жребий, какой ответ действительно заслуживает большого зеленого чека.Я отдаю это ответу, за который, к сожалению, проголосовали отрицательно, который содержит не только достойный ответ, но и множество разъяснений и информации в ветке комментариев.Честно говоря, здесь нет одного лучшего ответа, их как минимум три :)
Решение
Я думаю, вы не упомянули одну вещь: пространство и распределение.Примитивы являются типами значений и выделяются в стеке (пока они не связаны с объектом), за исключением строкового типа, как вы упомянули (класс строки выделяет свое пространство в куче).
Хотя сами объекты содержат примитивы, их хранилище находится там, где выделен фактический объект, то есть в куче.
Кроме того, ваше заявление довольно хорошо написано.У вас есть конкретный вопрос, который я пропустил :)?
Другие советы
Я просто хотел добавить здесь небольшую заметку.
Спецификация языка C# четко определяет «литерал»: литерал — это представление значения в исходном коде.Литералы — это такие вещи, как true
, 10
, 5.7
, 'c'
, "hello"
и ноль - они есть текст который представляет собой конкретное значение.
В спецификации языка C# слово «примитивный» используется дважды;оно никогда не определено и совершенно неясно относительно того, что оно может означать.
В спецификации языка C# нет необходимости использовать или определять слово «примитивный», и поэтому не следует использовать этот расплывчатый термин.Я поговорил с Мэдсом, и мы договорились, что будущие редакции спецификации будут перефразированы, чтобы полностью исключить такое использование.
То, как другие спецификации систем типов — библиотека отражения, CLI, VES и т. д. — определяют слово «примитивный», конечно, зависит от них.
Спасибо, что подняли вопрос.
Верно ли мое понимание (если не объяснение) по большей части?
Не согласен в одном пункте:Литерал — это своего рода константа времени компиляции (например, "Hello World"
, 5
или 'A'
).Однако не существует «литеральных типов»;литерал всегда является фактическим значением.
Примитивные типы — это «базовые» типы IMO, такие как string, int, double, float, short,...
Настолько примитивны, что с ними связаны свои типы литералов.
Да, литерал — это значение, выраженное в исходном коде, поэтому, хотя VB поддерживает литералы даты/времени и XML, C# этого не делает.
Из спецификации C#, раздел 2.4.4:
А буквальный является представлением исходного кода значения.
Как вы говорите, это не связано с типом значения и ссылочным типом - строка действительно является ссылочным типом.
Один литерал, о котором еще никто не упомянул. null
кстати...
Это также не связано с примитивными типами - от Type.IsPrimitive
:
Примитивными типами являются логические, байт, Sbyte, Int16, Uint16, Int32, Uint32, Int64, Uint64, Intptr, Uintptr, Char, Double и Single.
...спецификация C# на самом деле не определяет идею «примитивного» типа, но обратите внимание, что String
нет в списке выше.
С точки зрения литералов, являющихся константами времени компиляции...в C# каждый литерал имеет представление, которое можно встроить непосредственно в сборку;дополнительные литералы в VB означают, что они не являются константами в том смысле, в каком их понимает CLR, — у вас не может быть const DateTime
например, но они все еще литералы.
Здесь это страница MSDN, посвященная CLS, которая включает в себя нить как примитивный тип:
Библиотека класса .NET Framework включает типы, которые соответствуют примитивным типам данных, которые используют компиляторы.Из этих типов следующие представлены CLS:Byte, Int16, Int32, Int64, сингл, двойной, логический, чар, десятичный, Intptr и String.Для получения дополнительной информации об этих типах см. В таблице типов в библиотеке .NET Framework.
Не забывайте, что существует также Класс ASP.Net Literal.
РЕДАКТИРОВАТЬ:Таким образом, ответ на вопрос в заголовке — нет, поскольку не существует «Примитивного» класса, обеспечивающего ту же функциональность.Хотя это можно рассматривать как своего рода умный ответ Алека.
Я думаю, что ваше понимание в основном правильное.Как сказал winSharp93, литералы — это значения, которые сами по себе имеют типы, но не существует такого понятия, как «тип литерала».То есть, хотя у вас могут быть строковые литералы, строки не являются «литеральным типом».Как вы уже догадались, литерал определяется тем, что значение непосредственно записано в исходном коде, хотя ваше требование о том, чтобы не указывать тип, кажется слишком строгим (например,F# имеет литералы массива и может определить тип литерала массива. [| 1; 2; 3 |]
, но не обязательно может определить тип пустого литерала массива [| |]
).
К сожалению, я не думаю, что существует общепринятое определение того, что является примитивом.Конечно, как указывает Джон Скит, в CLR есть собственное определение примитивности (Type.IsPrimitive
), что исключает строки.Однако, другие авторитетные источники учитывать string
и даже object
быть примитивными типами в C#.Я предпочитаю это определение, поскольку в C# имеется встроенная поддержка строк, например использование оператора +
оператор конкатенации и использования ==
как равенство значений, а не равенство ссылок, а также тот факт, что к строковому типу можно обращаться с использованием короткой формы string
вместо того, чтобы использовать полное имя System.String
.
Просто добавим, что есть еще один тип, который стирает ограничения: System.Decimal
чьи значения могут быть выражены как литералы в С# язык, но который не является .Net примитивный тип.
ИМХО примитивные типы можно просто определить как типы, которые непосредственно «существуют» в каждом базовом платформа/хост:если вы уже играли с языком ассемблера, вы знаете, что у вас есть байты, слова, двойные слова...но у вас нет строк или десятичных знаков.
Действительно .Чистые десятичные дроби являются "подражал" средой выполнения .Net и не обрабатываются напрямую оборудованием, которое понимает только ИЭЭЭ 754 числа с плавающей запятой (float и double, которые тогда являются примитивными типами).
Расширяя понятие буквальных значений «Литеральные типы» можно рассматривать как любой тип, значения которого могут быть непосредственно выражены на данном языке (C#, VB.Net, CIL...).С этим определением литеральные типы будут: все примитивные типы + строки + десятичные дроби.