В чем разница между строкой и строкой в ​​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.