Sự khác biệt giữa Chuỗi và chuỗi trong C # là gì?


6509

Ví dụ ( lưu ý trường hợp ):

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

Các hướng dẫn cho việc sử dụng từng là gì? Và sự khác biệt là gì?


72
@ORMapper, nhưng thực tế vẫn stringlà một cấu trúc từ vựng của ngữ pháp C # trong khi System.Stringchỉ là một loại. Bất kể sự khác biệt rõ ràng nào được đề cập trong bất kỳ thông số kỹ thuật nào, vẫn có sự khác biệt ngầm này có thể được bổ sung với một số sự mơ hồ. Bản thân ngôn ngữ phải hỗ trợ stringtheo cách mà việc triển khai không (hoàn toàn) vì vậy bắt buộc phải xem xét cho một lớp cụ thể trong BCL.
Kirk Woll

106
@KirkWoll: Theo đặc tả ngôn ngữ, bản thân ngôn ngữ phải được coi stringlà giống hệt như loại BCL System.String, không có gì khác. Điều đó không mơ hồ chút nào. Tất nhiên, bạn có thể triển khai trình biên dịch của riêng mình, sử dụng ngữ pháp C # và sử dụng tất cả các mã thông báo được tìm thấy như thế cho một cái gì đó tùy ý, không liên quan đến những gì được xác định trong đặc tả ngôn ngữ C #. Tuy nhiên, ngôn ngữ kết quả sẽ chỉ là một giao diện C #, nó không thể được coi là C #.
HOẶC Mapper

88
Bạn có thể sử dụng stringmà không cần sử dụng chỉ thị cho Hệ thống. Bạn không thể làm điều đó với String.
Wilsu

14
Đối với ai đó đến từ Algol và Fortran, cuộc thảo luận này cho thấy có điều gì đó không ổn string. Nó là cần thiết để viết tắt System.String, nhưng, như một bí danh, nó có vẻ khá thích, nhưng không hoàn toàn giống nhau. Sau nhiều năm C #, tuy nhiên, tôi muốn nói, nó là an toàn để sử dụng đơn giản stringstring.Format()và không lo lắng về System.String.
Roland

8
@Sangeeta Bạn đang nói gì vậy? Các System.Stringlớp vẫn còn đó, và stringtừ khóa vẫn là một bí danh cho nó. Chỉ thích System.Int32int. Họ đúng là cùng một điều.
Craig

Câu trả lời:


6105

stringlà một bí danh trong C # cho System.String.
Vì vậy, về mặt kỹ thuật, không có sự khác biệt. Nó giống như int so với System.Int32 .

Theo như hướng dẫn, thông thường nên sử dụng stringbất cứ lúc nào bạn đang đề cập đến một đối tượng.

ví dụ

string place = "world";

Tương tự như vậy, tôi nghĩ rằng nó thường được khuyến khích sử dụng Stringnếu bạn cần tham khảo cụ thể về lớp học.

ví dụ

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

Đây là phong cách mà Microsoft có xu hướng sử dụng trong các ví dụ của họ .

Có vẻ như hướng dẫn trong lĩnh vực này có thể đã thay đổi, vì StyleCop hiện thực thi việc sử dụng các bí danh cụ thể C #.


163
Nếu bạn quyết định sử dụng StyleCop và tuân theo điều đó, điều đó sẽ nói là sử dụng các loại dành riêng cho ngôn ngữ. Vì vậy, đối với C #, bạn sẽ có chuỗi (thay vì Chuỗi), int (thay vì Int32), float (thay vì Đơn) - stylecop.soyuz5.com/SA1121.html
Dominic Zukiewicz

144
Tôi luôn sử dụng các bí danh vì tôi cho rằng một ngày nào đó nó có thể có ích vì chúng hoạt động như một sự trừu tượng, do đó có thể thay đổi cách triển khai của chúng mà tôi không cần phải biết.
Cướp

37
Visual Studio 2015 nói rằng String.Format nên được đổi thành chuỗi.Format, vì vậy tôi đoán Microsoft đang đi theo hướng đó. Tôi cũng đã luôn sử dụng String cho các phương thức tĩnh.
Sami Kuhmonen

32
Khi tôi đọc qua những điều này, tôi nhận thấy một số ý kiến ​​đơn giản là không chính xác. @ DRAirey1 Trong thời gian, bạn sẽ thấy rằng cách cũ vẫn là tốt nhất, nếu bạn nghi ngờ điều đó thì tôi dám thử viết mã C # mà không cần sử dụng Visual Studio. Điều này hầu như không thể và đôi khi xuất hiện trong công việc phát triển web. @Vlad Bạn không cần nhập bất cứ thứ gì để sử dụng String. @ Abhi Nhận xét của bạn là vô nghĩa và không kém phần đúng cho string.Format(). @KlitosG Không, điều đó không đúng. Tất cả đều hoạt động giống hệt nhau.
krowe2

46
Bạn có thể thêm một nhận xét rằng trên thực tế, có một sự khác biệt? Ví dụ: nameof(string)sẽ không biên dịch trong khi nameof(String)sẽ.
Jeroen Vannevel

3439

Chỉ vì mục đích hoàn chỉnh, đây là một đống thông tin liên quan ...

Như những người khác đã lưu ý, stringlà một bí danh cho System.String. Chúng biên dịch thành cùng một mã, vì vậy tại thời điểm thực hiện không có sự khác biệt nào. Đây chỉ là một trong những bí danh trong C #. Danh sách đầy đủ là:

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

Ngoài stringobject, các bí danh là tất cả các loại giá trị. decimallà một loại giá trị, nhưng không phải là loại nguyên thủy trong CLR. Loại nguyên thủy duy nhất không có bí danh là System.IntPtr.

Trong thông số kỹ thuật, các bí danh loại giá trị được gọi là "các loại đơn giản". Chữ có thể được sử dụng cho các giá trị không đổi của mọi loại đơn giản; không có loại giá trị nào khác có sẵn theo nghĩa đen. (So ​​sánh điều này với VB, cho phép bằng DateTimechữ và cũng có bí danh cho nó.)

Có một trường hợp trong đó bạn phải sử dụng các bí danh: khi chỉ định rõ ràng loại cơ bản của enum. Ví dụ:

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

Đó chỉ là vấn đề của con đường spec định nghĩa enum tờ khai - phần sau dấu hai chấm phải là không thể thiếu kiểu sản xuất, đó là một chiếc thẻ của sbyte, byte, short, ushort, int, uint, long, ulong, char... như trái ngược với một loại sản xuất như được sử dụng bởi các khai báo biến chẳng hạn. Nó không chỉ ra sự khác biệt nào khác.

Cuối cùng, khi nói đến việc sử dụng: cá nhân tôi sử dụng các bí danh ở mọi nơi để triển khai, nhưng loại CLR cho bất kỳ API nào. Nó thực sự không quan trọng quá nhiều mà bạn sử dụng về mặt triển khai - tính nhất quán trong nhóm của bạn là tốt, nhưng không ai khác sẽ quan tâm. Mặt khác, điều thực sự quan trọng là nếu bạn đề cập đến một loại trong API, bạn sẽ làm như vậy theo cách trung lập về ngôn ngữ. Một phương thức được gọi ReadInt32là không rõ ràng, trong khi một phương thức được gọi ReadIntyêu cầu giải thích. Ví dụ, người gọi có thể đang sử dụng một ngôn ngữ xác định intbí danh Int16. Các nhà thiết kế .NET framework đã theo mô hình này, các ví dụ tốt là trong BitConverter, BinaryReaderConvertcác lớp học.


82
Tình hình thừa kế với enum là thú vị. Bạn có thể chỉ ra tài liệu về lý do tại sao bí danh phải được sử dụng để liệt kê? Hay đây là một lỗi đã biết?
JaredPar

149
Nó nằm trong phần 14.1 của thông số kỹ thuật (Tôi không thể trích dẫn dễ dàng ở đây vì nó quá dài). Nó không rõ ràng nói rằng bạn phải sử dụng bí danh, nhưng các bí danh là loại điều trị như các loại riêng của họ. Tất cả đều hơi lạ.
Jon Skeet

32
@PiPeep điều đáng kinh ngạc hơn số lượng upvote lớn là số lượng downvote thấp đáng kinh ngạc (hãy xem xét 5 bài đăng hàng đầu có tổng số hơn 2000 upvote và chỉ có 1 downvote trong số đó). Đặc biệt là khi bạn xác định rằng luôn có "kẻ thù ghét" trong bất kỳ cộng đồng nào, tôi thực sự thấy điều đó đơn giản đến khó tin.
corsiKa

40
Một sự khác biệt thú vị giữa stringStringđó là string' is a keyword in c#, so you can not use it as a variable name.For Ex: chuỗi chuỗi = "hi"; //compiler error, but Chuỗi String = "hi"; `có thể chấp nhận được, vì đây Stringlà một định danh không phải là một từ khóa.
Sanjeev Rai

33
@SanjeevRai: Vâng. Bạn có thể sử dụng @stringđể tạo một định danh mà cuối cùng là như stringvậy. Đó là một loại cơ chế thoát.
Jon Skeet

716

Stringlà viết tắt của System.Stringnó và nó là một loại .NET Framework. stringlà một bí danh trong ngôn ngữ C # cho System.String. Cả hai đều được biên dịch sang System.StringIL (Ngôn ngữ trung gian), vì vậy không có sự khác biệt. Chọn những gì bạn thích và sử dụng đó. Nếu bạn viết mã bằng C #, tôi thích stringđó là bí danh loại C # và được các lập trình viên C # nổi tiếng biết đến.

Tôi có thể nói tương tự về ( int, System.Int32) vv ..


3
`Nếu bạn viết mã bằng C #, tôi thích chuỗi hơn vì đó là bí danh loại C # và được các lập trình viên C # nổi tiếng '- khi đó một người C # sẽ không biết .NET framework. +1 như tôi nghĩ nói chung đây là câu trả lời tốt nhất, nhưng điểm tôi đề cập có vẻ kỳ quặc.
MyDaftQuestions

4
Cá nhân tôi thích sử dụng "Int32" hơn, vì nó ngay lập tức hiển thị phạm vi của giá trị. Hãy tưởng tượng nếu họ nâng cấp loại "int" trên các hệ thống bit cao hơn sau này. 'int' trong c rõ ràng được xem là "loại số nguyên mà bộ xử lý đích hoạt động hiệu quả nhất" và được định nghĩa là "ít nhất 16 bit". Tôi muốn sự nhất quán có thể dự đoán ở đó, cảm ơn bạn rất nhiều.
Nyerguds

2
@MyDaftQuestions tôi đồng tình. Nếu bất cứ điều gì sẽ hợp lý khi sử dụng các loại .net vì chúng không biết gì về ngôn ngữ và loại này rõ ràng, không phụ thuộc vào bất kỳ ngôn ngữ nào (tôi có biết tất cả các đặc điểm riêng của F # hay VB không?).
Peter - Tái lập Monica

5
@Nyerguds Có hai lý do để đơn giản là không lo lắng về nó. Một là intđược xác định trong thông số ngôn ngữ C # là số nguyên 32 bit bất kể phần cứng. C #, mặc dù có một di sản được chia sẻ theo thời gian, nhưng thực tế không phải C. Thay đổi intthành số nguyên 64 bit sẽ là một thay đổi đột phá trong đặc tả và ngôn ngữ. Nó cũng sẽ yêu cầu xác định lại long, như longhiện tại là số nguyên 64 bit. Một lý do khác để không phải lo lắng là không liên quan vì các loại sẽ không bao giờ thay đổi, nhưng .NET chỉ đủ trừu tượng để 99% thời gian bạn không phải nghĩ về nó. ;-)
Craig

5
@Craig tôi thâm nhập vào rất nhiều định dạng trò chơi độc quyền cũ nơi tôi làm phải suy nghĩ về điều đó tất cả các thời điểm đó, mặc dù. Và sau đó sử dụng Int16, Int32Int64là một rất nhiều minh bạch hơn trong các mã hơn bằng cách sử dụng chứ không phải nondescriptive short, intlong
Nyerguds

505

Câu trả lời hay nhất tôi từng nghe về việc sử dụng các bí danh loại được cung cấp trong C # đến từ Jeffrey Richter trong cuốn sách CLR Via C # của ông . Dưới đây là 3 lý do của anh ấy:

  • Tôi đã thấy một số nhà phát triển bối rối, không biết nên sử dụng chuỗi hay Chuỗi trong mã của họ. Bởi vì trong C #, chuỗi (từ khóa) ánh xạ chính xác đến System.String (loại FCL), không có sự khác biệt và có thể được sử dụng.
  • Trong C #, ánh xạ dài tới System.Int64 , nhưng trong một ngôn ngữ lập trình khác, dài có thể ánh xạ tới Int16 hoặc Int32 . Trên thực tế, C ++ / CLI trên thực tế coi nó là Int32 . Ai đó đọc mã nguồn bằng một ngôn ngữ có thể dễ dàng hiểu sai ý định của mã nếu người đó được sử dụng để lập trình bằng ngôn ngữ lập trình khác. Trong thực tế, hầu hết các ngôn ngữ thậm chí sẽ không đối xử với dài như một từ khóa và sẽ không biên dịch mã mà sử dụng nó.
  • FCL có nhiều phương thức có tên kiểu như là một phần của tên phương thức của chúng. Ví dụ, loại BinaryReader cung cấp các phương thức như ReadBoolean , ReadInt32 , ReadSingle , v.v. và loại System.Convert cung cấp các phương thức như ToBoolean , ToInt32 , ToSingle , v.v. Mặc dù việc viết mã sau đây là hợp pháp, nhưng dòng có cảm giác rất không tự nhiên đối với tôi và không rõ ràng là dòng đó là chính xác:
BinaryReader br = new BinaryReader(...);
float val  = br.ReadSingle(); // OK, but feels unnatural
Single val = br.ReadSingle(); // OK and feels good

Vì vậy, có bạn có nó. Tôi nghĩ rằng đây là tất cả những điểm thực sự tốt. Tuy nhiên, tôi không thấy mình sử dụng lời khuyên của Jeffrey trong mã của riêng tôi. Có thể tôi quá bế tắc trong thế giới C # của mình nhưng cuối cùng tôi cố gắng làm cho mã của mình trông giống như mã khung.


24
Điểm thứ hai nghe có vẻ thực sự giống như một lý do không sử dụng string, intv.v.
MauganRa

15
@MauganRa Và nó được cho là, tác giả của cuốn sách liệt kê những lý do đó là tại sao anh ta không sử dụng bí danh.
tomi.lee.jones

31
"Nếu ai đó đang đọc mã nguồn C #, họ nên diễn giải dài theo thông số ngôn ngữ, chứ không phải thông số ngôn ngữ khác." Điều đó bỏ lỡ điểm hoàn toàn. Không phải ai cũng có ý định giải thích sai mã, đơn giản là bộ não của một người dễ dàng đi đến kết luận sai khi một loại có ý nghĩa khác với những gì lập trình viên nhìn thấy hàng ngày trong bối cảnh khác. Tất cả chúng ta đều phạm sai lầm; sử dụng các loại được đặt tên rõ ràng làm cho những sai lầm ít có khả năng.
Darryl

10
+ Những lý do này tổng hợp cảm xúc của tôi về vấn đề này. Khi tôi lần đầu tiên bắt đầu viết mã bằng C # (đến từ nền Java / C ++ / C), tôi đã nghĩ các bí danh là xấu. Tôi vẫn cảm thấy như vậy, thật không may, hầu hết thế giới dường như không đồng ý với tôi, hoặc họ không quan tâm, và vì vậy hãy sử dụng chữ thường.
gusgorman

8
@jinzai câu hỏi là về C #, trong đó longđược định nghĩa là số nguyên 64 bit đã ký, bất kể nền tảng hay trình biên dịch. Vì vậy, trong một số trường hợp ít nhất, có, nó không phụ thuộc vào ngôn ngữ.
phoog

455

stringlà một từ dành riêng, nhưng Stringchỉ là một tên lớp. Điều này có nghĩa là stringkhông thể được sử dụng như một tên biến.

Nếu vì lý do nào đó bạn muốn một biến có tên là chuỗi , bạn sẽ chỉ thấy biến đầu tiên trong số các biên dịch này:

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

Nếu bạn thực sự muốn một tên biến được gọi là chuỗi, bạn có thể sử dụng @làm tiền tố:

StringBuilder @string = new StringBuilder();

Một sự khác biệt quan trọng khác: Stack Overflow làm nổi bật chúng khác nhau.


20
Hãy nhớ rằng việc gọi một địa phương @stringthực sự là khá vô nghĩa, vì tên của người dân địa phương chỉ có trong PDB. Cũng có thể gọi nó _stringhoặc một cái gì đó. Nó có ý nghĩa hơn đối với những thứ có tên có thể truy cập thông qua sự phản chiếu, trong đó tên của một @stringthành viên sẽ là "string".
Roman Starkov

25
Ngoài ra, hãy nhớ sử dụng một từ dành riêng như một tên biến là không phù hợp.
Elton

7
OP không muốn sử dụng Chuỗi hoặc chuỗi làm tên biến. Họ yêu cầu một lời giải thích về sự khác biệt giữa các loại này . Câu trả lời của bạn chỉ phục vụ để thêm sự nhầm lẫn IMO
Matt Wilko

1
@craig nếu bạn đang viết phần mềm để dạy mọi người cách thắt nút?
Simon_Weaver

5
@Simon_Weaver thắt nút trong chuỗi? haha, tốt lắm. :-) Tất nhiên, bạn có thể chọn một tên thay thế, như chủ đề. Đợi một chút ... Ôi!
Craig

391

Có một sự khác biệt - bạn không thể sử dụng Stringmà không cần using System;trước.


14
theo mặc định, hầu hết mọi người đều thêm phần này vào bất kỳ cách nào ở đầu tệp. VS làm điều này theo mặc định trong hầu hết các trường hợp không phải tất cả!
IbrarMumtaz

9
Theo mặc định, tôi chỉ thêm các usingcâu tôi yêu cầu và loại bỏ rõ ràng tất cả những gì tôi không làm. Công cụ năng suất năng lượng> "[x] Xóa và định dạng sử dụng khi lưu"
JMD

2
@JMD Tôi đã sửa đổi tệp mẫu .cs để nó thậm chí không có bất kỳ câu lệnh sử dụng nào ở trên cùng! Tôi cũng đã thay đổi mẫu lớp thành internal sealed.
ErikE

@JMD Tôi ghét tính năng đó. Đôi khi, nó thực hiện các thay đổi trên các tệp chưa được xử lý, làm cho khó thấy những thay đổi thực tế mà một thay đổi chứa. Tất nhiên tôi thường loại bỏ "sử dụng thư rác", nhưng chỉ chủ động, không tự động.
mg30rg

Điều đó có thể đúng với C #, nhưng không phải tất cả các ngôn ngữ .NET. (Powershell nhập không gian tên Hệ thống theo mặc định.)
FSCKur

311

Nó đã được bảo hiểm ở trên; tuy nhiên, bạn không thể sử dụng stringđể phản ánh; bạn phải sử dụng String.


6
Tôi không hiểu câu trả lời này có nghĩa là gì và tại sao nó lại được nêu lên. Bạn có thể sử dụng typeof(string)trong sự phản ánh. Ví dụ một: if (someMethodInfo.ReturnType == typeof(string)) { ... }Ví dụ hai: var p = typeof(string).GetProperty("FirstChar", BindingFlags.NonPublic | BindingFlags.Instance);Bạn phải sử dụng ở đâu String, không phải string? Nếu bạn thử những thứ như Type.GetType("String")hoặc Type.GetType("string"), sẽ không tìm thấy lớp vì không gian tên bị thiếu. Nếu vì một lý do ngớ ngẩn nào đó, bạn so sánh .Namemột loại với "string"một cách phân biệt chữ hoa chữ thường, bạn đã đúng.
Jeppe Stig Nielsen

256

System.Stringlà lớp chuỗi .NET - trong C # stringlà bí danh cho System.String- vì vậy trong sử dụng chúng giống nhau.

Về hướng dẫn, tôi sẽ không quá sa lầy và chỉ sử dụng bất cứ điều gì bạn cảm thấy thích - có những điều quan trọng hơn trong cuộc sống và dù sao thì mã cũng sẽ giống nhau.

Nếu bạn thấy mình xây dựng các hệ thống mà nó là cần thiết để xác định kích thước của các số nguyên bạn đang sử dụng và do đó có xu hướng sử dụng Int16, Int32, UInt16, UInt32vv sau đó nó có thể trông tự nhiên hơn để sử dụng String- và khi di chuyển xung quanh giữa các ngôn ngữ .net khác nhau nó có thể làm cho mọi thứ dễ hiểu hơn - nếu không tôi sẽ sử dụng chuỗi và int.


2
Chỉ cần chọn một và được nhất quán. Nếu bạn làm việc ở đâu đó với phong cách ngôi nhà, hãy sử dụng nó.
Alan B

3
Thật không may, phong cách là sở thích cá nhân và có thể quá đắt để thực thi trong một cơ sở mã lớn trên nhiều nhóm mà không có chủ sở hữu mã chuyên dụng. luôn luôn có nhiều vấn đề quan trọng cần quan tâm hơn là chuỗi vs String. điều này đưa chúng ta trở lại với "những điều quan trọng hơn trong cuộc sống"
aiodintsov 24/2/2016

Đây chắc chắn là một điều ưu tiên; ví dụ: Tôi thích sử dụng short, int, ushort, uintthay vì Int16vv Chủ yếu là bởi vì đây là cách tôi học được. Cấp, Int16dễ hiểu hơn ngay lập tức cho những người có ít kinh nghiệm. +1 từ tôi!
Cand Meatark

210

Tôi thích các .NETkiểu viết hoa (hơn là các bí danh) vì lý do định dạng. Các .NETloại được tô màu giống như các loại đối tượng khác (xét cho cùng, các loại giá trị là các đối tượng thích hợp).

Các từ khóa có điều kiện và kiểm soát (như if, switchreturn) là chữ thường và được tô màu xanh đậm (theo mặc định). Và tôi thà không có sự bất đồng trong sử dụng và định dạng.

Xem xét:

String someString; 
string anotherString; 

11
Bạn cũng viết mã như: Int32 i = 1; Thay vì int i = 1; ? Có vẻ không nhất quán khi không sử dụng bí danh chuỗi khi nó có sẵn.
bytedev

29
@nashwan: thực sự, vâng, tôi sử dụng Int32 i=1;intstead của int i = 1; tôi thấy cái trước đây dễ đọc hơn theo ý định của tôi: cụ thể là tôi muốn một số nguyên có chữ ký 32 bit.
NotMe

5
Tôi đoán tất cả phụ thuộc vào việc nhà phát triển nghĩ rằng họ đang viết mã C # (chuỗi) hay mã .NET (Chuỗi). Cá nhân tôi nghĩ rằng tôi đang viết C # (và đó là C # đang sử dụng .NET).
bytedev

7
@Alex: quan điểm của tôi đơn giản là tôi thích rất cụ thể trong mã hóa của mình để xóa bỏ sự mơ hồ.
NotMe

22
Ở đầu kia của quang phổ, tôi hầu như luôn luôn sử dụngvar
tic

192

stringStringgiống hệt nhau theo mọi cách (ngoại trừ chữ hoa "S"). Không có ý nghĩa hiệu suất một trong hai cách.

Chữ thường stringđược ưa thích trong hầu hết các dự án do tô sáng cú pháp


Jeffrey Richter khuyên bạn nên sử dụng loại CLR trong mọi trường hợp (CLR qua C #) để tránh chính xác loại nhầm lẫn đang diễn ra ở đây.
Josh

Rõ ràng, cho dù bạn sử dụng S hay s, nó sẽ gây ra câu hỏi này, vì vậy hãy bỏ phiếu Richter. ;)
Brad Wilson

Richter có nghĩa là chuỗi không nên là một tùy chọn - Microsoft không nên có ngôn ngữ đó. Bạn không thể bình chọn Richter - anh ấy là một huyền thoại! :)
Joe Ratzer

1
Tôi đồng ý rằng có lẽ tốt hơn là không có bí danh nào cả. Nhưng cho rằng chúng ta có chúng, tôi nghĩ sẽ tốt khi sử dụng chúng (nhưng không phải trong tên phương thức, v.v.)
Jon Skeet

10
"Chuỗi" không giống như "Chuỗi". Có nghĩa là "System.String". Vì vậy, nếu bạn sử dụng "Chuỗi", bạn phải đặt "bằng cách sử dụng Hệ thống" để bao gồm không gian tên
ThiagoAlves

185

C # là ngôn ngữ được sử dụng cùng với CLR.

string là một loại trong C #.

System.String là một loại trong CLR.

Khi bạn sử dụng C # cùng với CLR stringsẽ được ánh xạ tới System.String.

Về mặt lý thuyết, bạn có thể triển khai trình biên dịch C # tạo mã byte Java. Một triển khai hợp lý của trình biên dịch này có thể sẽ ánh xạ stringtới java.lang.Stringđể tương tác với thư viện thời gian chạy Java.


1
stringkhông phải là một loại trong C #; đó là một từ dành riêng ánh xạ tới một loại trong CLR.
CesarGon

@CesarGon: Theo ECMA-334, phần 8.2.1: "C # cung cấp một tập hợp các loại được xác định trước [...] Các loại tham chiếu được xác định trước là đối tượng và chuỗi."
Rasmus Faber

10
Theo ECMA-334, mục 9.4.3, "chuỗi" là một từ khóa. :-) Tôi đồng ý với bạn rằng "chuỗi" là một loại nếu bạn tập trung vào ngữ nghĩa, nhưng tôi sẽ nói đó là một từ khóa (tức là một từ dành riêng) nếu bạn tập trung vào cú pháp. Các tiêu chuẩn ủng hộ cả hai quan điểm (có lẽ quá mơ hồ!). Đối với tôi, OP là về cú pháp, vì vậy tôi có xu hướng tập trung vào cú pháp khi tôi nhìn vào câu trả lời, nhưng tôi cũng thấy quan điểm của bạn. Hơn nữa, câu trả lời của bạn, có thể được hiểu là có nghĩa là hai loại khác nhau tồn tại: chuỗi và Chuỗi, khi đó không phải là trường hợp. Một cái là ánh xạ tới cái kia.
CesarGon

Hãy rõ ràng về điều này. 'chuỗi' là một bí danh dành riêng. Nó không phải là một kiểu dữ liệu thực sự. Nó là một cái gì đó chỉ vào một cái gì đó khác. Bạn có thể xóa tất cả các bí danh này (hoặc không bao giờ sử dụng chúng) và có một ngôn ngữ lập trình hoàn toàn tốt.
Quarkly

168

Video YouTube này cho thấy thực tế chúng khác nhau như thế nào.

Nhưng bây giờ cho một câu trả lời văn bản dài.

Khi chúng ta nói về .NETcó hai thứ khác nhau, một cái có .NETkhung và cái kia có ngôn ngữ ( C#, VB.NETv.v.) sử dụng khung đó.

nhập mô tả hình ảnh ở đây

" System.String" aka "Chuỗi" (viết hoa "S") là .NETkiểu dữ liệu khung trong khi "chuỗi" là C#kiểu dữ liệu.

nhập mô tả hình ảnh ở đây

Trong ngắn hạn "Chuỗi" là một bí danh (cùng một tên được gọi với các tên khác nhau) của "chuỗi". Vì vậy, về mặt kỹ thuật cả hai câu lệnh mã dưới đây sẽ cho cùng một đầu ra.

String s = "I am String";

hoặc là

string s = "I am String";

Theo cách tương tự, có các bí danh cho loại dữ liệu c # khác như được hiển thị bên dưới: -

object : System.Object, string : System.String, bool : System.Boolean, byte : System.Byte, sbyte : System.SByte, short: System.Int16vân vân

Bây giờ câu hỏi triệu đô theo quan điểm của lập trình viên Vậy khi nào nên sử dụng "Chuỗi" và "chuỗi"?

Điều đầu tiên để tránh nhầm lẫn sử dụng một trong số họ một cách nhất quán. Nhưng từ quan điểm thực tiễn tốt nhất khi bạn thực hiện khai báo biến, nên sử dụng "chuỗi" ("s" nhỏ) và khi bạn đang sử dụng nó làm tên lớp thì "Chuỗi" (viết hoa "S") được ưu tiên.

Trong đoạn mã dưới đây, phía bên trái là một khai báo biến và nó được khai báo bằng cách sử dụng "chuỗi". Ở phía bên tay phải, chúng ta đang gọi một phương thức để "Chuỗi" hợp lý hơn.

string s = String.ToUpper() ;

25
"Tóm lại" Chuỗi "là một bí danh (cùng một tên được gọi với các tên khác nhau) của" chuỗi "". Điều này không chính xác: bí danh là "chuỗi".
Xavier Egea

3
Khi bạn khai báo biến, tốt nhất là sử dụng "chuỗi" ("s" nhỏ) và khi bạn đang sử dụng nó làm tên lớp thì "Chuỗi" (viết hoa "S") được ưu tiên. Quy ước này dường như không còn hợp lệ: nếu bạn sử dụng Visual Studio 2015 và cố gắng viết Stringnó đề nghị bạn "đơn giản hóa mã của mình", mang nó đến string...
Massimiliano Kraus

165

Chữ thường stringlà một bí danh cho System.String. Họ giống nhau trong C#.

Có một cuộc tranh luận về việc liệu bạn nên sử dụng các loại hệ thống ( System.Int32, System.String, vv) loại hoặc C# aliases( int, string, vv). Cá nhân tôi tin rằng bạn nên sử dụng C# aliases, nhưng đó chỉ là sở thích cá nhân của tôi.


4
Đó là vấn đề, chúng không phải là bí danh 'C #', chúng là bí danh 'C'. Không có 'chuỗi' hoặc 'int' riêng trong ngôn ngữ C #, chỉ là cú pháp cú pháp.
Quarkly

16
không chắc chắn "C" đến từ đâu, vì đặc tả ngôn ngữ C # 5 có nội dung "Chuỗi từ khóa chỉ đơn giản là một bí danh cho lớp System.String được xác định trước." ở trang 85, đoạn 4.2.4. Tất cả các ngôn ngữ cấp cao là đường cú pháp trên tập lệnh CPU và mã byte.
aiodintsov

156

stringchỉ là một bí danh cho System.String. Trình biên dịch sẽ xử lý chúng giống hệt nhau.

Sự khác biệt thực tế duy nhất là cú pháp tô sáng khi bạn đề cập và bạn phải viết using Systemnếu bạn sử dụng String.


Bạn không cần tiền tố Hệ thống để sử dụng Chuỗi.
Joe Ratzer

18
Bạn phải bao gồm một using Systemkhi sử dụng String, nếu không bạn sẽ gặp phải lỗi sau:The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
Ronald

143

Cả hai đều giống nhau. Nhưng từ quan điểm hướng dẫn mã hóa, tốt hơn là sử dụng stringthay vì String. Đây là những gì các nhà phát triển thường sử dụng. ví dụ thay vì sử dụng Int32chúng ta sử dụng intnhư intbí danh đểInt32

Chuỗi từ khóa chỉ đơn giản là một bí danh cho lớp được xác định trước System.String. - Đặc tả ngôn ngữ C # 4.2.3 http://msdn2.microsoft.com/En-US/l Library / aa691153.aspx


120

Như những người khác đang nói, họ giống nhau. Quy tắc StyleCop, theo mặc định, sẽ thi hành bạn sử dụng stringnhư một C # mã phong cách thực hành tốt nhất, ngoại trừ khi tham khảo System.Stringchức năng tĩnh, chẳng hạn như String.Format, String.Join, String.Concat, vv ...


4
Tôi không biết rằng StyleCop sẽ gắn cờ sử dụng Chuỗi - ngoại trừ các phương thức tĩnh. Tôi nghĩ điều đó thật tuyệt vì đó là cách tôi luôn sử dụng nó: chuỗi cho khai báo kiểu và Chuỗi khi tôi truy cập các thành viên tĩnh.
Goyuix

101

Câu trả lời mới sau 6 năm và 5 tháng (chần chừ).

Mặc dù stringlà một từ khóa C # dành riêng luôn có một ý nghĩa cố định, Stringchỉ là một từ định danh thông thường có thể đề cập đến bất cứ điều gì. Tùy thuộc vào các thành viên của loại hiện tại, không gian tên hiện tại và các usingchỉ thị được áp dụng và vị trí của chúng, Stringcó thể là một giá trị hoặc một loại khác biệt với global::System.String.

Tôi sẽ cung cấp hai ví dụ trong đó các usingchỉ thị sẽ không giúp đỡ .


Đầu tiên, khi nào Stringlà một giá trị của loại hiện tại (hoặc một biến cục bộ):

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

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

Ở trên sẽ không biên dịch vì IEnumerable<>không có thành viên không tĩnh được gọi Formatvà không áp dụng các phương thức mở rộng. Trong trường hợp trên, vẫn có thể sử dụng Stringtrong các bối cảnh khác trong đó một loại là khả năng duy nhất về mặt cú pháp. Ví dụ String local = "Hi mum!";có thể là OK (tùy thuộc vào không gian tên và usingchỉ thị).

Tệ hơn: Nói String.Concat(someSequence)sẽ có khả năng (tùy thuộc vào usings) vào phương thức mở rộng Linq Enumerable.Concat. Nó sẽ không đi đến phương thức tĩnh string.Concat.


Thứ hai, khi Stringlà một loại khác , được lồng bên trong loại hiện tại:

class MyPiano
{
  protected class String
  {
  }

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

Không có câu lệnh nào trong Examplephương thức biên dịch. Đây Stringluôn là một cây đàn piano chuỗi , MyPiano.String. Không có thành viên ( statichoặc không) Formattồn tại trên nó (hoặc được kế thừa từ lớp cơ sở của nó). Và giá trị "Goodbye"không thể được chuyển đổi thành nó.


4
Tôi cho rằng một người mắc bệnh tiểu đường có thể: using String = System.Int32; using Int32 = System.String; và sau đó đếm các lỗi.
Steve

7
đây là câu trả lời đúng. stringSystem.String. Stringcó thể là bất cứ thứ gì.
Dave Cousineau

Đồng ý @DaveCousineau - đó là điểm của bí danh. Bạn có thể tạo một Stringloại khác sẽ không được đặt thành đối tượng System.String. Kiểm tra: blog.paranoidcoding.com/2019/04/08/ Cách
Kristopher

"Từ khóa stringcó ý nghĩa cụ thể trong C #. Đây là loại System.Stringtồn tại trong tập hợp thời gian chạy cốt lõi. Về cơ bản thời gian chạy hiểu loại này và cung cấp các khả năng mà các nhà phát triển mong đợi stringstrong .NET. Sự hiện diện của nó rất quan trọng đối với C # nếu loại đó không Không tồn tại trình biên dịch sẽ thoát trước khi cố phân tích một dòng mã. Do đó string, nó có ý nghĩa chính xác, rõ ràng trong mã C #. Mã định danh Stringmặc dù không có ý nghĩa cụ thể trong C #. Đây là một mã định danh đi qua tất cả các quy tắc tra cứu tên. as Widget,, Studentvân vân "
Kristopher



87

Chống lại những gì dường như là thông lệ phổ biến trong số các lập trình viên khác, tôi thích Stringhơn string, chỉ để làm nổi bật thực tế đó Stringlà một loại tham chiếu, như Jon Skeet đã đề cập.



78

Tôi chỉ muốn thêm câu này vào câu trả lời của lfousts, từ cuốn sách của Ritchers:

Thông số kỹ thuật của ngôn ngữ C #, Giao dịch là một vấn đề về phong cách, việc sử dụng từ khóa được ưu tiên hơn so với việc sử dụng tên loại hệ thống hoàn chỉnh. Tôi không đồng ý với đặc tả ngôn ngữ; Tôi thích sử dụng tên loại FCL và tránh hoàn toàn tên loại nguyên thủy. Trên thực tế, tôi ước rằng các trình biên dịch thậm chí không cung cấp tên loại nguyên thủy và buộc các nhà phát triển sử dụng tên loại FCL thay thế. Đây là lý do của tôi:

  • Tôi đã thấy một số nhà phát triển bối rối, không biết nên sử dụng chuỗi hay Chuỗi trong mã của họ. Bởi vì trong chuỗi C # (một từ khóa) ánh xạ chính xác đến System.String (loại FCL), không có sự khác biệt và có thể được sử dụng. Tương tự, tôi đã nghe một số nhà phát triển nói rằng int đại diện cho số nguyên 32 bit khi ứng dụng đang chạy trên HĐH 32 bit và nó đại diện cho số nguyên 64 bit khi ứng dụng đang chạy trên HĐH 64 bit. Tuyên bố này hoàn toàn sai: trong C #, một int luôn ánh xạ tới System.Int32 và do đó, nó đại diện cho một số nguyên 32 bit bất kể hệ điều hành mà mã đang chạy. Nếu lập trình viên sẽ sử dụngInt32 trong mã của họ, sau đó sự nhầm lẫn tiềm năng này cũng được loại bỏ.

  • Trong C #, ánh xạ dài tới System.Int64 , nhưng trong một ngôn ngữ lập trình khác, dài có thể ánh xạ tới Int16 hoặc Int32 . Trong thực tế, C ++ / CLI không điều trị dài như một Int32 . Ai đó đọc mã nguồn bằng một ngôn ngữ có thể dễ dàng hiểu sai ý định của mã nếu người đó được sử dụng để lập trình bằng ngôn ngữ lập trình khác. Trong thực tế, hầu hết các ngôn ngữ thậm chí sẽ không đối xử với dài như một từ khóa và sẽ không biên dịch mã mà sử dụng nó.

  • FCL có nhiều phương thức có tên kiểu như là một phần của tên phương thức của chúng. Ví dụ, loại BinaryReader cung cấp các phương thức như ReadBoolean , ReadInt32 , ReadSingle , v.v. và loại System.Convert cung cấp các phương thức như ToBoolean , ToInt32 , ToSingle , v.v. Mặc dù đó là pháp lý để viết đoạn mã sau, dòng với phao cảm thấy rất không tự nhiên với tôi, và nó không phải là rõ ràng rằng dòng là đúng:

    BinaryReader br = new BinaryReader(...);
    float val = br.ReadSingle(); // OK, but feels unnatural
    Single val = br.ReadSingle(); // OK and feels good
  • Nhiều lập trình viên sử dụng độc quyền C # có xu hướng quên rằng các ngôn ngữ lập trình khác có thể được sử dụng để chống lại CLR và vì điều này, các chủ đề C # leo vào mã thư viện lớp. Ví dụ, FCL của Microsoft được hầu như chỉ viết bằng C # và các nhà phát triển trong nhóm FCL giờ đây đã giới thiệu phương pháp vào thư viện như mảng ‘s GetLongLength , mà trả về một Int64 giá trị đó là một lâu trong C # nhưng không phải trong các ngôn ngữ khác (như C ++ / CLI). Một ví dụ khác là phương thức LongCount của System.Linq.Enumerable .

Tôi đã không nhận được ý kiến ​​của anh ấy trước khi tôi đọc đoạn hoàn chỉnh.


72

Chuỗi ( System.String) là một lớp trong thư viện lớp cơ sở. chuỗi (chữ thường) là một tác phẩm dành riêng trong C # là bí danh cho System.String. Int32 vs int là một tình huống tương tự như vậy Boolean vs. bool. Các từ khóa cụ thể của ngôn ngữ C # này cho phép bạn khai báo nguyên thủy theo kiểu tương tự C.


67

Stringkhông phải là một từ khóa và nó có thể được sử dụng làm Định danh trong khi đó stringlà một từ khóa và không thể được sử dụng làm Định danh. Và trong quan điểm chức năng cả hai đều giống nhau.


67

Đó là một vấn đề của hội nghị, thực sự. stringtrông giống phong cách C / C ++ hơn. Quy ước chung là sử dụng bất kỳ phím tắt nào mà ngôn ngữ bạn chọn đã cung cấp (int / Int for Int32). Điều này đi cho "đối tượng" và decimallà tốt.

Về mặt lý thuyết, điều này có thể giúp chuyển mã thành một số tiêu chuẩn 64 bit trong tương lai, trong đó "int" có thể có nghĩa Int64, nhưng đó không phải là vấn đề, và tôi hy vọng bất kỳ trình hướng dẫn nâng cấp nào sẽ thay đổi bất kỳ inttham chiếu Int32nào để đảm bảo an toàn.


66

Đến muộn trong bữa tiệc: Tôi sử dụng các loại CLR 100% thời gian (tốt, ngoại trừ nếu bị buộc sử dụng loại C #, nhưng tôi không nhớ lần cuối là khi nào).

Ban đầu tôi bắt đầu thực hiện cách đây nhiều năm, theo sách CLR của Ritchie. Điều này có ý nghĩa với tôi rằng tất cả các ngôn ngữ CLR cuối cùng phải có khả năng hỗ trợ tập hợp các loại CLR, do đó, việc sử dụng các loại CLR tự cung cấp rõ ràng hơn và có thể mã "tái sử dụng" nhiều hơn.

Bây giờ tôi đã làm điều đó trong nhiều năm, đó là một thói quen và tôi thích màu sắc mà VS thể hiện cho các loại CLR.

Điều duy nhất thực sự là tự động hoàn thành sử dụng loại C #, vì vậy tôi kết thúc việc gõ lại các loại được tạo tự động để chỉ định loại CLR thay thế.

Ngoài ra, bây giờ, khi tôi thấy "int" hoặc "chuỗi", nó trông có vẻ rất sai đối với tôi, giống như tôi đang xem mã C của 1970.


49

Không có sự khác biệt.

Từ khóa C # stringánh xạ tới loại .NET System.String- đó là một bí danh tuân theo các quy ước đặt tên của ngôn ngữ.

Tương tự, intbản đồ đến System.Int32.


Trong bản dựng 64 bit, int ánh xạ tới System.Int64 (8 byte), trong bản dựng 32 bit, nó ánh xạ tới System.Int32 (4 byte)
Alex

1
IntPtr và UIntPtr là các loại duy nhất thay đổi kích thước theo nền tảng (bỏ qua các loại con trỏ thực tế như int*và các loại bao gồm [U] IntPtr hoặc con trỏ thực tế).
P Daddy

45

Có một trích dẫn về vấn đề này từ cuốn sách của Daniel Solis .

Tất cả các loại được xác định trước được ánh xạ trực tiếp đến các loại .NET cơ bản. Tên loại C # (chuỗi) chỉ là bí danh cho các loại .NET (Chuỗi hoặc System.String), vì vậy sử dụng tên .NET hoạt động tốt về mặt cú pháp, mặc dù điều này không được khuyến khích. Trong chương trình C #, bạn nên sử dụng tên C # thay vì tên .NET.


41

chuỗi là một từ khóa và bạn không thể sử dụng chuỗi làm định danh.

Chuỗi không phải là một từ khóa và bạn có thể sử dụng nó như một định danh:

Thí dụ

string String = "I am a string";

Từ khóa string là một bí danh System.Stringngoài vấn đề từ khóa, hai từ này hoàn toàn tương đương.

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

2
Sự khác biệt nhỏ duy nhất là nếu bạn sử dụng lớp String, bạn cần nhập không gian tên Hệ thống trên đầu tệp của mình, trong khi bạn không phải làm điều này khi sử dụng từ khóa chuỗi.
Uttam

Có những trường hợp sử dụng đơn giản trong đó câu lệnh đẳng thức sẽ thất bại ... Chẳng hạn như xác định một chuỗi cuộc gọi kiểu trong không gian tên blah và nhập không gian tên đó vào tệp trong đó câu lệnh đẳng thức đang chạy.
rick

40

Vâng, đó không phải là sự khác biệt giữa chúng, giống như boolBoolean.


40

@JaredPar (một nhà phát triển trên trình biên dịch C # và người dùng SO prolific!) Đã viết một bài đăng blog tuyệt vời về vấn đề này. Tôi nghĩ rằng nó là giá trị chia sẻ ở đây. Đó là một viễn cảnh tốt đẹp về chủ đề của chúng tôi.

stringvs. Stringkhông phải là một cuộc tranh luận về phong cách

[...]

Từ khóa stringcó ý nghĩa cụ thể trong C #. Đây là loại System.Stringtồn tại trong cụm thời gian chạy lõi. Thời gian chạy thực sự hiểu loại này và cung cấp các khả năng mà các nhà phát triển mong đợi cho các chuỗi trong .NET. Sự hiện diện của nó rất quan trọng đối với C # đến nỗi nếu kiểu đó không tồn tại thì trình biên dịch sẽ thoát ra trước khi cố gắng phân tích một dòng mã. Do đó stringcó một ý nghĩa chính xác, rõ ràng trong mã C #.

Mã định danh Stringmặc dù không có ý nghĩa cụ thể trong C #. Nó là một mã định danh đi qua tất cả các quy tắc tra cứu tên như Widget, Studentv.v ... Nó có thể liên kết với chuỗi hoặc nó có thể liên kết với một loại trong một tổ hợp khác hoàn toàn có mục đích khác hoàn toàn string. Tệ hơn là nó có thể được định nghĩa theo cách mà mã như thế nào String s = "hello"; tiếp tục biên dịch.

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;
}

Ý nghĩa thực sự của Stringsẽ luôn phụ thuộc vào độ phân giải tên. Điều đó có nghĩa là nó phụ thuộc vào tất cả các tệp nguồn trong dự án và tất cả các loại được xác định trong tất cả các cụm được tham chiếu. Nói tóm lại, nó đòi hỏi khá nhiều bối cảnh để biết ý nghĩa của nó.

Đúng là trong phần lớn các trường hợp Stringstringsẽ liên kết với cùng loại. Nhưng sử dụng Stringvẫn có nghĩa là các nhà phát triển đang để chương trình của họ diễn giải ở những nơi chỉ có một câu trả lời đúng. Khi Stringliên kết với loại sai, nó có thể khiến các nhà phát triển gỡ lỗi trong nhiều giờ, báo lỗi cho nhóm trình biên dịch và thường lãng phí thời gian có thể được lưu bằng cách sử dụng string.

Một cách khác để hình dung sự khác biệt là với mẫu này:

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

Nhiều người sẽ lập luận rằng mặc dù đây là thông tin chính xác về mặt kỹ thuật sử dụng Stringvẫn tốt vì nó cực kỳ hiếm khi một cơ sở mã sẽ xác định một loại tên này. Hoặc khi Stringđược định nghĩa, đó là dấu hiệu của một cơ sở mã xấu.

[...]

Bạn sẽ thấy rằng Stringđược định nghĩa cho một số mục đích hoàn toàn hợp lệ: người giúp đỡ phản chiếu, thư viện serialization, lexers, các giao thức, vv ... Đối với bất kỳ của các thư viện này Stringvs stringcó hậu quả thực tùy thuộc vào nơi mã được sử dụng.

Vì vậy, hãy nhớ khi bạn thấy cuộc tranh luận Stringso với stringcuộc tranh luận này là về ngữ nghĩa, không phải phong cách. Chọn chuỗi mang lại ý nghĩa rõ ràng cho cơ sở mã của bạn. Lựa chọn Stringkhông sai nhưng nó sẽ mở ra những bất ngờ trong tương lai.

Lưu ý: Tôi sao chép / dán hầu hết các bài đăng trên blog vì lý do lưu trữ. Tôi bỏ qua một số phần, vì vậy tôi khuyên bạn nên bỏ qua và đọc bài đăng trên blog nếu bạn có thể.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.