В чем разница между строкой и строкой в ​​C #?


6514

Пример ( обратите внимание на случай ):

string s = "Hello world!";
String s = "Hello world!";

Каковы правила использования каждого из них? И в чем различия?


72
@ORMapper, но факт остается фактом string: это лексическая конструкция грамматики C #, тогда как System.Stringэто просто тип. Независимо от каких-либо явных различий, упомянутых в какой-либо спецификации, все еще существует неявное различие, которое можно допустить с некоторой неопределенностью. Сам язык должен поддерживать stringтаким образом, чтобы реализация (совсем) не была так обязательна для конкретного класса в BCL.
Кирк Волл

106
@KirkWoll: Согласно спецификации языка, а сам язык должен рассмотреть , stringчтобы быть точно такой же , как тип BCL System.String, больше ничего. Это совсем не двусмысленно. Конечно, вы можете реализовать свой собственный компилятор, используя грамматику C #, и использовать все найденные токены для чего-то произвольного, не связанного с тем, что определено в спецификации языка C #. Тем не менее, полученный язык будет похож на C #, его нельзя считать C #.
ИЛИ Mapper

88
Вы можете использовать stringбез использования директивы для системы. Вы не можете сделать это с String.
Wilsu

14
Для кого-то из Алгола и Фортрана это обсуждение показывает, что с ним что-то не так string. Его нужно сокращать System.String, но, как псевдоним, это выглядит примерно так, но не совсем так. После нескольких лет C #, хотя, я бы сказал, что это безопасно , чтобы просто использовать stringи string.Format()и не беспокоиться о System.String.
Роланд

8
@Sangeeta Что ты говоришь? System.StringКласс по - прежнему существует, и stringключевое слово по - прежнему является псевдонимом для него. Так же, как System.Int32и int. Они буквально одно и то же.
Крейг

Ответы:


6107

stringпсевдоним в C # для System.String.
Технически нет никакой разницы. Это как int против System.Int32 .

Что касается руководящих принципов, обычно рекомендуется использовать stringлюбое время, когда вы ссылаетесь на объект.

например

string place = "world";

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

например

string greet = String.Format("Hello {0}!", place);

Это стиль, который Microsoft стремится использовать в своих примерах .

Похоже, что руководство в этой области, возможно, изменилось, так как StyleCop теперь принудительно использует специальные псевдонимы C #.


163
Если вы решите использовать StyleCop и последуете этому, это будет означать использование типов, специфичных для языка. Таким образом, для C # у вас будет строка (вместо String), int (вместо Int32), float (вместо Single) - stylecop.soyuz5.com/SA1121.html
Доминик Цукевич

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

37
Visual Studio 2015 говорит, что String.Format должен быть изменен на string.Format, так что, думаю, Microsoft идет по этому пути. Я также всегда использовал String для статических методов.
Сами Кухмонен

32
Прочитав их, я заметил, что некоторые комментарии просто неверны. @ DRAirey1 Со временем вы обнаружите, что старый способ все еще остается лучшим, если вы сомневаетесь в этом, то я осмелюсь попытаться написать код C # без использования Visual Studio. Это практически невозможно, и ситуация, которая время от времени возникает в работе веб-разработки. @Vlad Вам не нужно ничего импортировать, чтобы использовать String. @Abhi Ваш комментарий не имеет смысла и одинаково верен для string.Format(). @ KlitosG Нет, это не правда. Все они работают одинаково.
krowe2

46
Не могли бы вы добавить замечание, что на самом деле есть разница? Например: nameof(string)не будет компилироваться, тогда как nameof(String)будет.
Йерун Ванневел

3441

Просто для полноты, вот мозговая свалка соответствующей информации ...

Как уже отмечали другие, stringэто псевдоним для System.String. Они компилируются в один и тот же код, поэтому во время выполнения нет никакой разницы. Это только один из псевдонимов в C #. Полный список:

object:  System.Object
string:  System.String
bool:    System.Boolean
byte:    System.Byte
sbyte:   System.SByte
short:   System.Int16
ushort:  System.UInt16
int:     System.Int32
uint:    System.UInt32
long:    System.Int64
ulong:   System.UInt64
float:   System.Single
double:  System.Double
decimal: System.Decimal
char:    System.Char

Помимо stringи object, псевдонимы все для значений типов. decimalявляется типом значения, но не примитивным типом в CLR. Единственный примитивный тип, у которого нет псевдонима, есть System.IntPtr.

В спецификации псевдонимы типа значения известны как «простые типы». Литералы могут использоваться для постоянных значений любого простого типа; никакие другие типы значений не имеют доступных литеральных форм. (Сравните это с VB, который допускает DateTimeлитералы, и тоже имеет псевдоним.)

Есть одно обстоятельство, при котором вы должны использовать псевдонимы: при явном указании основного типа перечисления. Например:

public enum Foo : UInt32 {} // Invalid
public enum Bar : uint   {} // Valid

Это просто вопрос того, как спецификация определяет перечислений деклараций - часть после двоеточия должен быть интегрально-типа производства, который один знак sbyte, byte, short, ushort, int, uint, long, ulong, char... , в отличие от типа производства , как используется в объявлениях переменных, например. Это не указывает на другие различия.

Наконец, когда дело доходит до использования: лично я использую псевдонимы везде для реализации, но тип CLR для любых API. На самом деле не имеет большого значения, какой вы используете с точки зрения реализации - согласованность в вашей команде - это хорошо, но больше никого не волнует. С другой стороны, действительно важно, что если вы ссылаетесь на тип в API, вы делаете это не зависящим от языка способом. Вызываемый метод ReadInt32является однозначным, тогда как вызываемый метод ReadIntтребует интерпретации. Вызывающий может использовать язык , например, для которого определяется intпсевдоним Int16. Каркасные .NET дизайнеры следовали этой модели, хорошие примеры будучи в BitConverter, BinaryReaderи Convertклассы.


82
Ситуация наследования с enum интересна. Можете ли вы указать на документацию, почему псевдоним должен использоваться для перечислений? Или это известная ошибка?
JaredPar

149
Это в разделе 14.1 спецификации (я не могу здесь легко цитировать, потому что это слишком долго). Он прямо не сказать , что вы должны использовать псевдоним, но псевдонимы рода рассматриваются как свои собственные типы. Это все немного странно.
Джон Скит

32
@PiPeep, что более поразительно, чем большое количество повышенных голосов - это ошеломляюще низкое количество отрицательных голосов (рассмотрим, что на верхних 5 постах в общей сложности более 2000 положительных голосов, и все же только один отрицательный голос среди них всех). Особенно, если учесть, что в любом сообществе всегда есть «ненавистники», я действительно считаю это просто невероятным.
CorsiKa

40
Одно интересное различие между stringи Stringзаключается в том, что string' is a keyword in c#, so you can not use it as a variable name.For Ex: string string = "hi"; //compiler error, but String String = "hi"; `допустимо, так как Stringявляется идентификатором, а не ключевым словом.
Санджив Рай

33
@SanjeevRai: Да. Вы можете использовать @stringдля создания идентификатора, который заканчивается как stringбудто. Это своего рода механизм побега.
Джон Скит

716

Stringозначает, System.Stringи это тип .NET Framework. stringпсевдоним в языке C # для System.String. Оба они скомпилированы System.Stringв IL (промежуточный язык), поэтому нет никакой разницы. Выберите то, что вам нравится, и используйте это. Если вы пишете код на C #, я бы предпочел, так stringкак это псевдоним C # и хорошо известен программистам C #.

Я могу сказать то же самое о ( int, System.Int32) и т.д ..


3
«Если вы пишете код на C #, я бы предпочел строку, так как это псевдоним C # и хорошо известен программистам C #» - когда человек на C # не знает фреймворк .NET. +1, как мне кажется, в общем, это лучший ответ, но пункт, который я упоминаю, кажется странным.
MyDaftQuestions

4
Я лично предпочитаю использовать «Int32», так как он сразу показывает диапазон значений. Представьте, обновили ли они тип int в более поздних старших системах. int в c, по-видимому, рассматривается как «целочисленный тип, с которым целевой процессор работает наиболее эффективно» , и определяется как «не менее 16 бит». Я бы предпочел предсказуемую последовательность, большое спасибо.
Nyerguds

2
@MyDaftQuestions Я согласен. Во всяком случае, имеет смысл последовательно использовать типы .net, потому что они не знают языка, а тип очевиден, независимо от какого-либо языка (знаю ли я все идиосинкразии F # или VB?).
Питер - Восстановить Монику

5
@ Nyerguds Есть две причины, чтобы просто не беспокоиться об этом. Одним из них является то, что intопределяется в спецификации языка C # как 32-битное целое число независимо от аппаратного обеспечения. C #, несмотря на общее наследие в глубине веков, на самом деле не является C. Изменение intна 64-битное целое число будет серьезным изменением в спецификации и языке. Это также потребовало бы переопределения long, как longв настоящее время 64-битное целое число. Другая причина не беспокоиться, не имеет значения, так как типы никогда не изменятся, но .NET достаточно абстрактен, так что 99% времени вам все равно не нужно думать об этом. ;-)
Крейг

5
@Craig Я копаюсь во множестве старых проприетарных игровых форматов, где мне все же приходится все время об этом думать. А затем , используя Int16, Int32и Int64это гораздо более прозрачным в коде , чем при использовании довольно nondescriptive short, intиlong
Nyerguds

506

Лучший ответ, который я когда-либо слышал об использовании предоставленных псевдонимов типов в C #, дан Джеффри Рихтером в его книге CLR Via C # . Вот его 3 причины:

  • Я видел, что некоторые разработчики были сбиты с толку, не зная, использовать ли в своем коде строку или строку . Поскольку в C # строка (ключевое слово) точно соответствует System.String (тип FCL), разницы нет, и любой из них может быть использован.
  • В C # long отображается на System.Int64 , но на другом языке программирования long может отображаться на Int16 или Int32 . Фактически, C ++ / CLI фактически обрабатывает долго как Int32 . Кто-то, читающий исходный код на одном языке, может легко неверно истолковать намерение кода, если он или она привыкли к программированию на другом языке программирования. На самом деле, большинство языков даже не рассматривают ключевое слово долго и не компилируют код, который его использует.
  • В FCL есть много методов, имена которых являются частью имен их методов. Например, тип BinaryReader предлагает такие методы, как ReadBoolean , ReadInt32 , ReadSingle и т. Д., А тип System.Convert предлагает такие методы, как ToBoolean , ToInt32 , ToSingle и т. Д. Хотя написать следующий код законно, строка с плавающей точкой кажется мне неестественной, и не очевидно, что строка правильная:
BinaryReader br = new BinaryReader(...);
float val  = br.ReadSingle(); // OK, but feels unnatural
Single val = br.ReadSingle(); // OK and feels good

Так что у вас есть это. Я думаю, что это действительно хорошие моменты. Однако я не использую советы Джеффри в своем собственном коде. Может быть, я слишком застрял в своем мире C #, но в итоге я пытаюсь сделать мой код похожим на фреймворк.


24
Второй пункт звучит как причина не использовать stringи intт. Д.
MauganRa

15
@MauganRa И, как предполагается, автор книги перечисляет эти причины того, почему он не использует псевдонимы.
tomi.lee.jones

31
«Если кто-то читает исходный код C #, он должен интерпретировать долго в соответствии со спецификацией языка, а не спецификацией других языков». Это полностью упускает из виду. Дело не в том, что кто-то намеревается неверно истолковать код, просто мозг легко делает неверный вывод, когда тип имеет другое значение, чем то, что программист видит ежедневно в другом контексте. Мы все делаем ошибки; использование явно названных типов делает эти ошибки менее вероятными.
Дэррил

10
+ Эти причины обобщают мои чувства по этому вопросу. Когда я впервые начал писать код на C # (исходя из фона Java / C ++ / C), я думал, что псевдонимы ужасны. Я до сих пор так думаю, к сожалению, большая часть мира, похоже, не согласна со мной, или им все равно, поэтому используйте строчные буквы.
gusgorman

8
@jinzai вопрос о C #, в котором longопределяется как 64-разрядное целое число со знаком , независимо от платформы или компилятора. Таким образом , в некоторых случаях , по крайней мере, да, это действительно зависит от языка.
фото

456

stringэто зарезервированное слово, но Stringэто просто имя класса. Это означает, что stringне может использоваться как имя переменной само по себе.

Если по какой-то причине вам нужна переменная с именем string , вы увидите только первый из этих компиляций:

StringBuilder String = new StringBuilder();  // compiles
StringBuilder string = new StringBuilder();  // doesn't compile 

Если вы действительно хотите имя переменной с именем string, вы можете использовать @в качестве префикса:

StringBuilder @string = new StringBuilder();

Еще одно критическое отличие: переполнение стека выделяет их по-разному.


20
Имейте в виду, что вызывать локальный код на @stringсамом деле довольно бессмысленно, поскольку его имена присутствуют только в PDB. С таким же успехом можно назвать это _stringили как-то так. Это имеет больше смысла для вещей, имена которых доступны через отражение, где будет имя @stringчлена "string".
Роман Старков

25
Также имейте в виду, что использование зарезервированного слова в качестве имени переменной крайне не элегантно.
Элтон

7
OP не хочет использовать строку или строку в качестве имени переменной. Они попросили объяснить разницу между этими типами . Ваш ответ только добавляет больше путаницы ИМО
Мэтт Вилко

1
@ Craig, если вы писали программное обеспечение, чтобы научить людей, как завязывать узлы?
Simon_Weaver

5
@Simon_Waaver завязывает в струнах? ха-ха забавно. :-) Конечно, вы можете выбрать другое имя, например, thread. Подожди минутку ...
Крейг

392

Есть одно отличие - вы не можете использовать Stringбез using System;заранее.


14
по умолчанию большинство людей добавляют это любым способом вверху файла. VS делает это по умолчанию в большинстве случаев не во всех!
ИбрарМумтаз

9
По умолчанию я добавляю только те usingоператоры, которые мне требуются, и явно удаляю все, что мне не нужно. Инструменты повышения производительности> «[x] Удаление и форматирование при сохранении»
JMD

2
@JMD Я изменил файл шаблона .cs, чтобы в нем даже не было операторов использования вверху! Я также изменил шаблон класса на internal sealed.
ErikE

@ JMD Я ненавижу эту функцию. Иногда он вносит изменения в другие нетронутые файлы, затрудняя просмотр фактических изменений, содержащихся в наборе изменений. Конечно, я обычно удаляю «используя спам», но только активно, а не автоматически.
mg30rg

Это может быть так для C #, но не для всех языков .NET. (Powershell по умолчанию импортирует пространство имен System.)
FSCKur

312

Это было покрыто выше; тем не менее, вы не можете использовать stringв отражении; Вы должны использовать String.


6
Я не понимаю, что означает этот ответ и почему за него проголосовали. Вы можете использовать typeof(string)в отражении. Пример первый: if (someMethodInfo.ReturnType == typeof(string)) { ... }Пример два: var p = typeof(string).GetProperty("FirstChar", BindingFlags.NonPublic | BindingFlags.Instance);где вы должны использовать String, а не string? Если вы попробуете что-то вроде Type.GetType("String")или Type.GetType("string"), ни один из них не найдет класс, потому что пространство имен отсутствует. Если по какой-то глупой причине вы сравниваете .Nameтип с "string"учетом регистра, вы правы.
Джепп Стиг Нильсен

257

System.Stringэто строковый класс .NET - в C # stringэто псевдоним для System.String- поэтому при использовании они одинаковы.

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

Если вы нашли себя строительные системы , где необходимо указать размер целых чисел , которые вы используете , и поэтому , как правило, использование Int16, Int32, UInt16, и UInt32т.д. , то это могло бы выглядеть более естественно использовать String- и, передвигаясь между различными языками .net это может сделать вещи более понятными - иначе я бы использовал string и int.


2
Просто выберите один и будьте последовательны. Если вы работаете где-то в стиле дома, используйте это.
Алан Б

3
к сожалению, стиль - это личное предпочтение, и он может быть слишком дорогим, чтобы его можно было применять в большой базе кода для нескольких команд без выделенного владельца кода. всегда есть более важные дела, чем строка против строки. что возвращает нас к «более важным вещам в жизни»
айодинцов

Это определенно вещь предпочтения; например: Я предпочитаю использовать short, int, ushort, uintвместо того Int16, и т.д. В основном потому , что это, как я узнал. Конечно, Int16это легче понять тем, у кого меньше опыта. +1 От меня!
Candleshark

211

Я предпочитаю прописные .NETтипы (а не псевдонимы) по причинам форматирования. Эти .NETтипы окрашены так же , как и другие типы объектов (типы значений являются собственными объектами, в конце концов).

Условные и управляющие ключевые слова (например if, switchи return) строчные и темно-синие (по умолчанию). И я бы предпочел не иметь разногласий в использовании и формате.

Рассматривать:

String someString; 
string anotherString; 

11
Ты тоже пишешь код вроде: Int32 i = 1; Вместо int i = 1; ? Кажется непоследовательным, чтобы не использовать псевдоним строки, когда он доступен.
Бытедев

29
@nashwan: на самом деле, да, я использую Int32 i=1;intstead of, int i = 1; я считаю, что первое является более читабельным в отношении моих намерений, а именно: я хочу получить 32-битное целое число со знаком.
NotMe

5
Ну, я думаю, все зависит от того, думает ли разработчик, что он пишет код C # (строка) или код .NET (строка). Лично я прежде всего думаю, что я пишу на C # (а это C #, который использует .NET).
bytedev

7
@ Алекс: моя точка зрения была просто в том, что я предпочитаю быть очень конкретным в своем кодировании, чтобы устранить двусмысленность.
NotMe

22
На другом конце спектра я почти всегда просто используюvar
тик

193

stringи Stringидентичны во всех отношениях (кроме заглавной буквы "S"). В любом случае нет никаких последствий для производительности.

Строчные буквы stringпредпочтительнее в большинстве проектов из-за подсветки синтаксиса


Джеффри Рихтер рекомендует использовать тип CLR во всех случаях (CLR через C #), чтобы избежать именно той путаницы, которая имеет место здесь.
Джош

Ясно, что если вы используете S или s, это вызовет эти вопросы, так что проголосуйте за Рихтера. ;)
Брэд Уилсон

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

1
Я согласен, что было бы лучше вообще не иметь псевдонимов. Но учитывая, что они у нас есть, я думаю, что их можно использовать (но не в именах методов и т. Д.)
Джон Скит

10
«строка» - это не то же самое, что «строка». Есть средство "System.String". Поэтому, если вы используете «String», вы должны добавить «using System» для включения пространства имен
ThiagoAlves

186

C # - это язык, который используется вместе с CLR.

string это тип в C #.

System.String это тип в CLR.

Когда вы используете C # вместе с CLR stringбудет отображаться наSystem.String .

Теоретически, вы могли бы реализовать C # -компилятор, который генерировал байт-код Java. Разумная реализация этого компилятора, вероятно карта stringдля java.lang.Stringтого , чтобы взаимодействовать с библиотекой времени выполнения Java.


1
stringне является типом в C #; это зарезервированное слово, которое отображается на тип в CLR.
CesarGon

@CesarGon: Согласно ECMA-334, раздел 8.2.1: «C # предоставляет набор предопределенных типов [...] Предопределенными ссылочными типами являются объект и строка».
Расмус Фабер

10
Согласно ECMA-334, раздел 9.4.3, «строка» является ключевым словом. :-) Я согласен с вами, что «строка» - это тип, если вы сосредоточены на семантике, но я бы сказал, что это ключевое слово (т.е. зарезервированное слово), если вы сосредоточены на синтаксисе. Стандарт поддерживает обе точки зрения (возможно, слишком неоднозначно!). Для меня ОП - это синтаксис, поэтому я склонен концентрироваться на синтаксисе, когда смотрю на ответы, но я вижу и вашу точку зрения. Кроме того, ваш ответ в его нынешнем виде может интерпретироваться как означающий, что существуют два разных типа: строка и строка, если это не так. Одно - это отображение на другое.
CesarGon

Давайте проясним это. 'string' является зарезервированным псевдонимом. Это не настоящий тип данных. Это то, что указывает на что-то еще. Вы можете удалить все эти псевдонимы (или просто никогда не использовать их) и иметь совершенно хороший язык программирования.
Quarkly

169

Это видео на YouTube демонстрирует, насколько они отличаются.

Но теперь для длинного текстового ответа.

Когда мы говорим о .NETдвух разных вещах, одна - это .NETфреймворк, а другая - языки ( C#и VB.NETт. Д.) , Которые используют эту фреймворк.

введите описание изображения здесь

" System.String" aka "String" (заглавная "S") - это .NETтип данных структуры, а "string" - это C#тип данных.

введите описание изображения здесь

Короче говоря, «String» - это псевдоним (то же самое, что называется с разными именами) «string». Таким образом, технически оба приведенных ниже кода дают одинаковый результат.

String s = "I am String";

или

string s = "I am String";

Таким же образом существуют псевдонимы для другого типа данных c #, как показано ниже:

object:, System.Objectstring:, System.Stringbool:, System.Booleanbyte:, System.Bytesbyte:, System.SByteshort: System.Int16и так далее

Теперь вопрос на миллион долларов с точки зрения программиста. Так когда же использовать «String» и «string»?

Прежде всего, чтобы избежать путаницы, используйте один из них последовательно. Но с точки зрения передового опыта, когда вы делаете объявление переменной, лучше использовать «string» (маленькие «s»), а когда вы используете его в качестве имени класса, тогда «String» (заглавная «S») предпочтительнее.

В приведенном ниже коде левая часть представляет собой объявление переменной, и оно объявлено с использованием «строки». В правой части мы вызываем метод, поэтому «String» более разумно.

string s = String.ToUpper() ;

25
«Короче говоря,« String »- это псевдоним (то же самое, что называется с разными именами)« string »». Это не правильно: псевдоним "строка".
Ксавье Эгеа,

3
когда вы делаете объявление переменной, хорошо использовать «string» (маленькие «s»), а когда вы используете его как имя класса, тогда «String» (заглавная «S») предпочтительнее. Это соглашение, кажется, больше не действует: если вы используете Visual Studio 2015 и пытаетесь написать Stringего, предложите «упростить свой код», перенеся его в string...
Массимилиано Краус

166

Нижний регистр stringявляется псевдонимом для System.String. Они одинаковые в C#.

Спорят о том, следует ли вам использовать типы System ( System.Int32, System.Stringи т. Д.) Или C# aliases( int, stringи т. Д.). Я лично считаю, что вы должны использовать C# aliases, но это только мое личное предпочтение.


4
В этом проблема, они не псевдонимы C #, а псевдонимы C. В языке C # нет нативных 'string' или 'int', только синтаксический сахар.
Quarkly

16
не знаю, откуда взялась буква «C», поскольку в спецификации языка C # 5 написано «Строка ключевого слова - это просто псевдоним для предопределенного класса System.String». на странице 85, пункт 4.2.4. Все языки высокого уровня являются синтаксическим сахаром над наборами команд ЦП и байт-кодом.
айодинцов

157

string это просто псевдоним для System.String . Компилятор будет относиться к ним одинаково.

Единственное практическое отличие - это подсветка синтаксиса, которую вы упоминаете, и которую вы должны написать, using Systemесли используете String.


Вам не нужно ставить префикс System для использования String.
Джо Ратцер

18
Вы должны включить using Systemпри использовании String, в противном случае вы получите следующую ошибку:The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
Ronald

144

Оба одинаковы. Но с точки зрения принципов кодирования лучше использовать stringвместо String. Это то, что обычно используют разработчики. Например, вместо использования Int32мы используем intкак intпсевдоним дляInt32

К вашему сведению «Строка ключевого слова - это просто псевдоним для предопределенного класса System.String». - Спецификация языка C # 4.2.3 http://msdn2.microsoft.com/En-US/library/aa691153.aspx


121

Как говорят другие, они одинаковы. Правила StyleCop, по умолчанию, будет обеспечивать , чтобы использовать в stringкачестве C # кода стиля передовой практики, кроме случаев , когда ссылки на System.Stringстатические функции, такие как String.Format, String.Join, String.Concatи т.д. ...


4
Я не знал, что StyleCop пометит использование String - за исключением статических методов. Я думаю, что это здорово, так как я всегда использую это: строка для объявлений типов и строка, когда я получаю доступ к статическим членам.
Goyuix

102

Новый ответ через 6 лет и 5 месяцев (промедление).

Хотя stringэто зарезервированное ключевое слово C #, которое всегда имеет фиксированное значение, Stringэто просто обычный идентификатор, который может ссылаться на что угодно. В зависимости от членов текущего типа текущее пространство имен и применяемые usingдирективы и их размещение Stringмогут быть значением или типом, отличным от global::System.String.

Я приведу два примера, где usingдирективы не помогут .


Во-первых, когда Stringэто значение текущего типа (или локальной переменной):

class MySequence<TElement>
{
  public IEnumerable<TElement> String { get; set; }

  void Example()
  {
    var test = String.Format("Hello {0}.", DateTime.Today.DayOfWeek);
  }
}

Вышеприведенное не будет компилироваться, поскольку IEnumerable<>не вызывается нестатический член Formatи методы расширения не применяются. В приведенном выше случае все еще возможно использовать Stringв других контекстах, где тип является единственной возможностью синтаксически. Например, String local = "Hi mum!";может быть в порядке (в зависимости от пространства имен иusing директив).

Хуже того: поговорка String.Concat(someSequence), скорее всего (в зависимости от usings), пойдет на метод расширения Linq Enumerable.Concat. Это не пойдет на статический метод string.Concat.


Во-вторых, когда Stringдругой тип , вложенный в текущий тип:

class MyPiano
{
  protected class String
  {
  }

  void Example()
  {
    var test1 = String.Format("Hello {0}.", DateTime.Today.DayOfWeek);
    String test2 = "Goodbye";
  }
}

Ни один оператор в Exampleметоде не компилируется. Здесь Stringвсегда пианино строка , MyPiano.String. Никакой член ( staticили нет) не Formatсуществует на нем (или унаследован от его базового класса). И ценность "Goodbye"не может быть преобразована в это.


4
Я полагаю, что быть дьявольским можно: using String = System.Int32; using Int32 = System.String; а потом считать ошибки.
Стив

7
это правильный ответ. stringесть System.String. Stringможет быть что угодно.
Дэйв Кузино

Договорились @DaveCousineau - это точка псевдонима. Вы можете создать другой Stringтип, который не будет установлен для объекта System.String. Проверьте: blog.paranoidcoding.com/2019/04/08/…
Кристофер

«Ключевое слово stringимеет конкретное значение в C #. Это тип, System.Stringкоторый существует в базовой сборке среды выполнения. Среда выполнения по сути понимает этот тип и предоставляет возможности, ожидаемые разработчиками stringsв .NET. Его наличие настолько важно для C #, что если этот тип не не существует, компилятор завершит работу, прежде чем пытаться даже проанализировать строку кода. Следовательно, stringимеет точное, однозначное значение в коде C #. Идентификатор, Stringхотя и не имеет конкретного значения в C #. Это идентификатор, который проходит через все правила поиска имен а Widget, Studentи т. д. "
Кристофер



88

Против того, что , как представляется, распространенной практикой среди других программистов, я предпочитаю Stringболее string, только чтобы подчеркнуть тот факт , что Stringэто ссылочный тип, как уже упоминалось Jon тарелочкам.



78

Я просто хотел бы добавить это к ответу lfousts из книги Ritchers:

Спецификация языка C # гласит: «По стилю использование ключевого слова предпочтительнее использования полного имени типа системы». Я не согласен с языковой спецификацией; Я предпочитаю использовать имена типов FCL и полностью избегать имен примитивных типов. На самом деле, я бы хотел, чтобы компиляторы даже не предлагали имена примитивных типов и заставляли разработчиков использовать вместо них имена типов FCL. Вот мои причины:

  • Я видел, что некоторые разработчики были сбиты с толку, не зная, использовать ли в своем коде строку или строку . Поскольку в C # string (ключевое слово) отображается точно на System.String (тип FCL), нет никакой разницы, и любой из них может быть использован. Точно так же я слышал, что некоторые разработчики говорят, что int представляет 32-разрядное целое число, когда приложение работает в 32-разрядной ОС, и что оно представляет 64-разрядное целое число, когда приложение выполняется в 64-разрядной ОС. Это утверждение абсолютно неверно: в C # int всегда отображается в Int32 в своем коде, тогда эта потенциальная путаница также устраняется. System.Int32 , и поэтому оно представляет 32-разрядное целое число независимо от ОС, в которой выполняется код. Если бы программисты использовали

  • В C # long отображается на System.Int64 , но на другом языке программирования long может отображаться на Int16 или Int32 . На самом деле, C ++ / CLI обрабатывает долго как Int32 . Кто-то, читающий исходный код на одном языке, может легко неверно истолковать намерение кода, если он или она привыкли к программированию на другом языке программирования. На самом деле, большинство языков даже не рассматривают ключевое слово долго и не компилируют код, который его использует.

  • В FCL есть много методов, имена которых являются частью имен их методов. Например, тип BinaryReader предлагает такие методы, как ReadBoolean , ReadInt32 , ReadSingle и т. Д., А тип System.Convert предлагает такие методы, как ToBoolean , ToInt32 , ToSingle и т. Д. Хотя написать следующий код законно, строка с плавающей точкой кажется мне неестественной, и не очевидно, что строка правильная:

    BinaryReader br = new BinaryReader(...);
    float val = br.ReadSingle(); // OK, but feels unnatural
    Single val = br.ReadSingle(); // OK and feels good
  • Многие программисты, использующие исключительно C #, склонны забывать, что другие языки программирования могут использоваться против CLR, и из-за этого C # -измы проникают в код библиотеки классов. Например, FCL Microsoft, почти исключительно написан на C # и разработчики в команде FCL теперь ввели методы в библиотеке , такой как массив «s GetLongLength , который возвращает Int64 значение , которое является длинным в C # , но не на других языках (например , C ++ / CLI). Другим примером может служить System.Linq.Enumerable «ы LongCount метод.

Я не получил его мнение, прежде чем я прочитал полный параграф.


72

String ( System.String) - это класс в библиотеке базовых классов. Строка (нижний регистр) - это зарезервированная работа в C #, которая является псевдонимом для System.String. Int32 против int похожая ситуация как есть Boolean vs. bool. Эти ключевые слова для языка C # позволяют вам объявлять примитивы в стиле, аналогичном C.


67

Stringне является ключевым словом и может использоваться в качестве идентификатора, тогда как stringявляется ключевым словом и не может использоваться в качестве идентификатора. И с функциональной точки зрения оба одинаковы.


67

Это действительно условно. stringпросто больше похоже на стиль C / C ++. Общее соглашение состоит в том, чтобы использовать любые ярлыки, предоставленные выбранным вами языком (int / Int для Int32). Это относится и к «объекту» decimal.

Теоретически это может помочь перенести код в какой-то будущий 64-битный стандарт, в котором может означать «int» Int64, но это не главное, и я ожидаю, что любой мастер обновления изменит любые intссылки на так Int32или иначе, чтобы быть безопасным.


66

Опаздываю на вечеринку: я использую типы CLR 100% времени (ну, за исключением случаев, когда вынужден использовать тип C #, но я не помню, когда это было в последний раз).

Первоначально я начал делать это несколько лет назад, в соответствии с книгами CLR Ричи. Для меня имело смысл, что в конечном итоге все языки CLR должны поддерживать набор типов CLR, поэтому использование типов CLR самостоятельно обеспечило более четкий и, возможно, более «многократно используемый» код.

Теперь, когда я делал это годами, это привычка, и мне нравится цвет, который VS показывает для типов CLR.

Единственный реальный недостаток заключается в том, что автозаполнение использует тип C #, поэтому я в итоге перепечатываю автоматически сгенерированные типы, чтобы вместо этого указать тип CLR.

Кроме того, теперь, когда я вижу «int» или «string», для меня это выглядит просто неправильно, как будто я смотрю на C-код 1970-х годов.


49

Нет никакой разницы.

Ключевое слово C # stringсоответствует типу .NET System.String- это псевдоним, который соответствует соглашениям об именах языка.

Аналогично, intкарты для System.Int32.


В 64-битной сборке int сопоставляется с System.Int64 (8 байт), в 32-битной сборке он сопоставляется с System.Int32 (4 байта)
Alex

1
IntPtr и UIntPtr являются единственными типами, которые изменяют размер в соответствии с платформой (не учитывая фактические типы указателей, такие как int*и типы, состоящие из [U] IntPtrs или фактических указателей).
P Daddy

45

Есть цитата по этому вопросу от книги Дэниела Солиса .

Все предопределенные типы отображаются непосредственно в базовые типы .NET. Имена типов C # (строка) являются просто псевдонимами для типов .NET (String или System.String), поэтому использование имен .NET синтаксически работает нормально, хотя это не рекомендуется. В программе на C # вы должны использовать имена C #, а не имена .NET.


41

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

Строка не является ключевым словом, и вы можете использовать его в качестве идентификатора:

пример

string String = "I am a string";

Ключевое слово string является псевдонимом System.Stringпомимо вопроса о ключевом слове, оба точно эквивалентны.

 typeof(string) == typeof(String) == typeof(System.String)

2
Единственное небольшое отличие состоит в том, что если вы используете класс String, вам необходимо импортировать пространство имен System в верхней части файла, тогда как вам не нужно делать это при использовании ключевого слова string.
Уттам

Существуют простые случаи использования, когда оператор равенства завершится ошибкой ... Например, определение вызова типа String в пространстве имен blah и импорт этого пространства имен в файл, в котором выполняется оператор равенства.
Rick


40

@JaredPar (разработчик компилятора C # и плодотворный пользователь SO!) Написал отличную запись в блоге на эту тему. Я думаю, что здесь стоит поделиться. Это хороший взгляд на нашу тему.

stringпротив Stringэто не стиль дебаты

[...]

Ключевое слово stringимеет конкретное значение в C #. Это тип, System.Stringкоторый существует в основной сборке времени выполнения. Среда выполнения по-настоящему понимает этот тип и предоставляет возможности, ожидаемые разработчиками для строк в .NET. Его присутствие настолько критично для C #, что, если этот тип не существует, компилятор завершит работу, прежде чем попытаться даже проанализировать строку кода. Следовательно, stringимеет точное, однозначное значение в коде C #.

StringХотя идентификатор не имеет конкретного значения в C #. Это идентификатор, который проходит через все правила поиска имен, как Widgetи Studentт. Д. Он может связываться со строкой или связываться с типом в другой сборке, цели которого могут полностью отличаться от string. Хуже того, это может быть определено таким образом, чтобы код был похож String s = "hello"; продолжил компилировать.

class TricksterString { 
  void Example() {
    String s = "Hello World"; // Okay but probably not what you expect.
  }
}

class String {
  public static implicit operator String(string s) => null;
}

Фактическое значение Stringвсегда будет зависеть от разрешения имени. Это означает, что это зависит от всех исходных файлов в проекте и всех типов, определенных во всех ссылочных сборках. Короче говоря, это требует довольно много контекста, чтобы знать того, что это значит, .

Правда, что в подавляющем большинстве случаев Stringи stringбудут связываться с однотипными. Но использование по- Stringпрежнему означает, что разработчики оставляют свою программу на интерпретацию в местах, где есть только один правильный ответ. Когда Stringпроисходит привязка к неправильному типу, это может привести к тому, что разработчики будут отлаживать часы в течение нескольких часов, регистрируя ошибки в команде компилятора и вообще тратя время, которое можно было бы сэкономить с помощью string.

Другой способ визуализировать разницу с этим примером:

string s1 = 42; // Errors 100% of the time  
String s2 = 42; // Might error, might not, depends on the code

Многие утверждают, что хотя технически точная информация Stringявляется хорошей, она по-прежнему хороша, потому что крайне редко кодовая база определяет тип этого имени. Или что когдаString это определено, это признак плохой базы кода.

[...]

Вы увидите , что Stringопределено для ряда вполне допустимых целей: отражение хелперов, библиотек сериализации, лексеры, протоколы и т.д. ... Для любого из этих библиотек по Stringсравнению stringимеет реальные последствия в зависимости от того, где используется код.

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

Примечание: я скопировал / вставил большую часть сообщения в блоге по причине архива. Я игнорирую некоторые части, поэтому я рекомендую пропустить и прочитать сообщение в блоге, если можете.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.