Яка різниця між рядком та рядком у C #?


6505

Приклад ( зверніть увагу на випадок ):

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

Які вказівки щодо використання кожного? А які відмінності?


72
@ORMapper, але факт залишається фактом, що stringце лексична конструкція граматики C #, тоді як System.Stringце лише тип. Незалежно від явної різниці, що згадується в будь-якій специфікації, все ж є ця неявна різниця, яка могла б відповідати деякій двозначності. Мова сама повинна підтримувати stringтаким чином, що реалізація не (цілком) настільки зобов'язана розглянути для певного класу в BCL.
Кірк Волл

106
@KirkWoll: Відповідно до мовної специфікації, сама мова повинна вважати stringточно такою ж, як тип BCL System.String, нічого іншого. Це зовсім не неоднозначно. Звичайно, ви можете реалізувати власний компілятор, використовуючи граматику C #, і використовувати всі знайдені лексеми для чогось довільного, не пов’язаного з тим, що визначено в специфікації мови C #. Однак мова, що виходить, була б лише lookalike C #, її не можна вважати C #.
АБО Mapper

88
Ви можете використовувати stringбез використання директиви для System. Ви не можете цього зробити String.
Вілсу

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

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

Відповіді:


6103

stringпсевдонім у C # for System.String.
Тож технічно різниці немає. Це як int VS. 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)збирається, тоді як буде.
Jeroen Vannevel

3439

Просто задля повноти, ось мозковий демпінг пов’язаної інформації ...

Як зазначали інші, 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
Цікава ситуація спадкування з перерахунком. Чи можете ви вказати на документацію, чому псевдонім потрібно використовувати для перерахування? Або це відома помилка?
JaredPar

149
Це в розділі 14.1 специфікації (я не можу тут легко процитувати, оскільки це занадто довго). Він прямо не сказати , що ви повинні використовувати псевдонім, але псевдоніми роду розглядаються як свої власні типи. Це все трохи дивно.
Джон Скіт

32
@PiPeep, що більш дивовижне, ніж велика кількість оновлень, - надзвичайно низька кількість рейтингів (врахуйте, що у перших 5 публікацій загалом понад 2000 змін, і все-таки лише 1 нижчий запис серед них). Тим більше, коли ви враховуєте думку про те, що в будь-якій громаді завжди є "ненависники", я дійсно вважаю це просто неймовірним.
corsiKa

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

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

715

Stringрозшифровується, System.Stringі це тип .NET Framework. stringпсевдонім мовою C # для System.String. Обидва вони складені System.Stringв IL (Intermediate Language), тому різниці немає. Виберіть те, що вам подобається, і використовуйте це. Якщо ви stringвводите код в C #, я вважаю за краще, оскільки це псевдонім типу 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

504

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

  • Я бачив, як ряд розробників плутаються, не знаючи, чи використовувати рядок або String у своєму коді. Оскільки в C # рядок (ключове слово) точно вказує на System.String (тип FCL), різниці немає і їх можна використовувати.
  • У C #, довгі карти для System.Int64 , але на іншій мові програмування, довго може відобразити на Int16 або Int32 . Насправді, C ++ / CLI насправді трактується як Int32 . Хтось, хто читає вихідний код однією мовою, може легко помилково витлумачити намір коду, якщо його або вона звикли програмувати іншою мовою програмування. Насправді більшість мов навіть довго не вважатимуться ключовим словом і не буде компілювати код, який його використовує.
  • FCL має багато методів, які містять назви типів як частину своїх назв методів. Наприклад, тип BinaryReader пропонує такі методи, як ReadBoolean , ReadInt32 , ReadSingle тощо, а тип System.Convert пропонує такі методи, як ToBoolean , ToInt32 , ToSingle тощо. Хоча законно писати наступний код, рядок з float вважає мене дуже неприродним, і не очевидно, що рядок правильний:
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), я подумав, що псевдоніми були некрасивими. Я все ще відчуваю це так, на жаль, більшість країн світу, здається, не згодні зі мною, або їм це не байдуже, і тому використовую малі регістри.
гусгорман

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

455

stringце зарезервоване слово, але Stringце лише назва класу. Це означає, що stringсама по собі не може використовуватися як ім'я змінної.

Якщо з якоїсь причини ви хотіли змінну під назвою string , ви побачили б лише першу з цих компіляцій:

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

Якщо ви дійсно хочете назву змінної під назвою рядок, ви можете використовувати @як префікс:

StringBuilder @string = new StringBuilder();

Ще одна важлива відмінність: переповнення стека виділяє їх по-різному.


20
Майте на увазі, що називати місцевого @stringжителя справді досить безглуздо, оскільки імена місцевих жителів є лише у PDB. Можна також назвати це _stringчи щось. Це має більше сенсу для речей, які мають імена, доступні через відображення, де було б ім’я @stringучасника "string".
Роман Старков

25
Також пам’ятайте, що використання зарезервованого слова як імені змінної є вкрай неелегантним.
Елтон

7
ОП не хоче використовувати рядок або рядок як ім'я змінної. Вони попросили пояснити різницю між цими типами . Ваша відповідь служить лише для додавання ще більше плутанини IMO
Метт Вілко

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

5
@Simon_Weaver вузли в рядках? ха-ха, приємно. :-) Звичайно, ви можете вибрати альтернативну назву, як нитка. Почекайте хвилинку ... D'oh!
Крейг

391

Існує одна різниця - ви не можете використовувати Stringбез using System;заздалегідь.


14
за замовчуванням більшість людей додають це будь-якими способами у верхній частині файлу. VS робить це за замовчуванням у більшості випадків не у всіх!
IbrarMumtaz

9
За замовчуванням я додаю лише usingпотрібні мені заяви і явно видаляю все те, чого я не хочу. Інструменти підвищення продуктивності живлення> "[x] Видаліть і відформатуйте вкладки при збереженні"
JMD

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

@JMD Я ненавиджу цю функцію. Іноді вносяться зміни в інакше недоторкані файли, що ускладнює розуміння, які фактичні зміни містить набір змін. Звичайно, я зазвичай видаляю "за допомогою спаму", але лише активно, не автоматично.
mg30rg

Це може бути так для C #, але не для всіх .NET мов. (Powershell імпортує простір імен системи за замовчуванням.)
FSCKur

311

Це було висвітлено вище; однак, ви не можете використовувати 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"чутливим до регістру способом, ви маєте рацію.
Jeppe Stig Nielsen

256

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

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

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


2
Просто виберіть один і будьте послідовні. Якщо ви працюєте десь із будинковим стилем, використовуйте це.
Алан Б

3
на жаль, стиль є особистим уподобанням і може бути занадто дорогим для застосування у великій базі коду для кількох команд без виділеного власника коду. завжди є важливіші питання, про які слід подбати, а не струна проти String. що повертає нас до "важливіших речей у житті"
айодінцов

Це, безумовно, перевагу; наприклад: Я вважаю за краще використовувати short, int, ushort, uintзамість того Int16, і т.д. У основному тому , що це, як я дізнався. Зрозуміло, тим Int16легше зрозуміти тим, хто має менший досвід. +1 Від мене!
Candleshark

210

Я вважаю за краще .NETформати з великої літери (а не псевдоніми) з міркувань форматування. Ці .NETтипи пофарбовані так само , як і інші типи об'єктів (типи значень є власними об'єктами, в кінці кінців).

Умовні та контрольні ключові слова (як if, switchі return) - це малі та кольорові темно-сині кольори (за замовчуванням) І я б швидше не мав розбіжностей у використанні та форматі.

Поміркуйте:

String someString; 
string anotherString; 

11
Ви також пишете код на зразок: Int32 i = 1; Замість int i = 1; ? Здається, непослідовно, щоб не використовувати псевдонім рядка, коли це доступно.
bytedev

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

5
Я думаю, все залежить від того, думає розробник, що вони пишуть код C # (рядок) або код .NET (String). Особисто я передусім думаю, що я пишу C # (і це C #, який використовує .NET).
bytedev

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

22
На абсолютному іншому кінці спектру, я майже завжди просто використовуватиvar
хрестики

192

stringі Stringоднакові за всіма параметрами (крім великої літери "S"). Жодних наслідків для продуктивності немає.

Рядкові stringє кращим в більшості проектів , в зв'язку з підсвічуванням синтаксису


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

Зрозуміло, що ви користуєтесь S або s, це спричинило ці питання, тож голосуйте за Ріхтера. ;)
Бред Уілсон

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

1
Я погоджуюся, що, можливо, було б краще взагалі не мати псевдонімів. Але з огляду на те, що у нас їх є, я думаю, що добре використовувати їх (але не в назвах методів тощо)
Джон Скіт,

10
"string" - це не те саме, що "String". Є засобом "System.String". Тож якщо ви використовуєте "String", вам потрібно поставити "using System", щоб включити простір імен
ThiagoAlves

185

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
Згідно з розділом 9.4.3 ECMA-334 "рядок" - це ключове слово. :-) Я згоден з вами, що "рядок" - це тип, якщо ви зосереджуєтесь на семантиці, але я б сказав, що це ключове слово (тобто зарезервоване слово), якщо ви зосереджуєтесь на синтаксисі. Стандарт підтримує обидві точки зору (можливо, занадто неоднозначно!). Для мене ОП стосується синтаксису, тому я схильний зосереджуватися на синтаксисі, коли я дивлюсь відповіді, але бачу і вашу думку. Крім того, Ваша відповідь, як вона є, може трактуватися так, що означає, що існує два різних типи: string та String, коли це не так. Одне - відображення іншого.
CesarGon

Давайте з цим будемо зрозумілі. 'string' є зарезервованим псевдонімом. Це не справжній тип даних. Це щось, що вказує на щось інше. Ви можете видалити всі ці псевдоніми (або просто ніколи не використовувати їх) і мати ідеально хорошу мову програмування.
Quarkly

168

Це відео 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 "". Це неправильно: псевдонім - "рядок".
Xavier Egea

3
коли ви робите оголошення змінної, добре використовувати "string" (малий "s"), а коли ви використовуєте його як назву класу, тоді "String" (з великої літери "S"). Ця конвенція, мабуть, не є більш чинною: якщо ви користуєтеся Visual Studio 2015 і намагаєтесь її написати, Stringто вам пропонується "спростити код", перенісши його до string...
Масміліміано Краус

165

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

Там в дискусії про те, чи слід використовувати типи системи ( 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. Всі мови високого рівня - це синтаксичний цукор над набором інструкцій CPU та байт-кодом.
айодінцов

156

stringце лише псевдонім для System.String. Компілятор буде ставитися до них однаково.

Єдина практична відмінність - це виділення синтаксису, як ви згадуєте, і те, що вам потрібно писати, using Systemякщо ви використовуєте String.


Вам не потрібно префіксу Система, щоб використовувати 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?)
Рональд

143

Обидва однакові. Але з точки зору настанов щодо кодування краще використовувати stringзамість цього String. Це те, що зазвичай розробники використовують. наприклад, замість того, щоб використовувати Int32ми використовуємо intяк intпсевдонімInt32

FYI "Рядок ключових слів - це просто псевдонім для попередньо визначеного класу System.String." - Специфікація мови C # 4.2.3 http://msdn2.microsoft.com/En-US/library/aa691153.aspx


120

Як кажуть інші, вони однакові. Правила StyleCop, за замовчуванням, буде забезпечувати , щоб використовувати в stringякості C # коду стилю передової практики, крім випадків , коли посилання на System.Stringстатичні функції, такі як String.Format, String.Join, String.Concatі т.д. ...


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

101

Нова відповідь через 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тощо ... "
Крістофер



87

Проти того, що , як видається, поширеною практикою серед інших програмістів, я вважаю за краще Stringбільш string, тільки щоб підкреслити той факт , що Stringце контрольний тип, як уже згадувалося Jon тарілочках.



78

Я просто хотів би додати це до відповіді lfousts, із книги Ritchers:

У специфікації мови C # зазначено: "Що стосується стилю, використання ключового слова сприятливо для використання повного імені типу системи". Я не згоден з мовною специфікацією; Я вважаю за краще використовувати імена типів FCL і повністю уникати прізвищ примітивних типів. Насправді, я хотів би, щоб компілятори навіть не пропонували імен примітивних типів і змусили розробників використовувати назви типів FCL. Ось мої причини:

  • Я бачив, як ряд розробників плутаються, не знаючи, чи використовувати рядок або String у своєму коді. Оскільки в рядку C # (ключове слово) точно вказується на System.String (тип FCL), різниці немає і їх можна використовувати. Так само я чув, як деякі розробники кажуть, що int являє собою 32-розрядне ціле число, коли програма працює на 32-бітній ОС і що вона представляє 64-бітове ціле число, коли програма працює на 64-бітній ОС. Це твердження абсолютно помилкове: у C # int завжди відображається на System.Int32 , і тому він являє собою 32-бітове ціле число незалежно від ОС, на якій працює код. Якби програмісти використали бInt32 в їх коді, тоді ця потенційна плутанина також усувається.

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

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

    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 vs int - подібна ситуація, як і раніше Boolean vs. bool. Ці ключові слова для мови C # дозволяють оголошувати примітиви у стилі, подібному до C.


67

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


67

Це справді питання конвенції. stringпросто більше нагадує стиль C / C ++. Загальна умова полягає у використанні будь-яких ярликів, які вибрала ваша мова (int / Int for Int32). Це стосується і "об'єкта" decimal.

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


66

Запізнюючись на вечірку: я використовую типи CLR 100% часу (ну, за винятком випадків, коли змушений використовувати тип C #, але я не пам'ятаю, коли це було останній раз).

Я спочатку почав це робити років тому, відповідно до книг CLR Річі. Мені було сенс, що всі мови CLR повинні врешті-решт мати можливість підтримувати набір типів CLR, тому використовуючи типи CLR, ви надали чіткіший і, можливо, більше "багаторазовий" код.

Тепер, коли я роблю це роками, це звичка, і мені подобається забарвлення, яке показує VS для типів CLR.

Єдиний справжній недоступ - це те, що при автоматичному завершенні використовується тип C #, тому я закінчую повторне введення автоматично створених типів, щоб замість цього вказати тип CLR.

Крім того, зараз, коли я бачу "int" або "string", мені це виглядає справді неправильно, як я переглядаю код C 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 тато

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, вам потрібно імпортувати системний простір імен поверх вашого файлу, тоді як вам не потрібно робити цього під час використання рядкового ключового слова.
Уттам

Існують прості випадки використання, коли заява про рівність виявиться невдалим ... Наприклад, визначення типу рядка виклику в просторі імен Blah та імпорт цього простору імен у файл, у якому запущено оператор рівності.
рик


40

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

stringvs. 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.