ความแตกต่างระหว่างสตริงและสตริงใน C # คืออะไร?


6505

ตัวอย่าง ( หมายเหตุกรณี ):

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

แนวทางการใช้งานของแต่ละคนมีอะไรบ้าง และอะไรคือความแตกต่าง?


72
@ORMapper แต่ความจริงยังคงstringเป็นโครงสร้างคำศัพท์ของไวยากรณ์ C # ในขณะที่System.Stringเป็นเพียงประเภท โดยไม่คำนึงถึงความแตกต่างที่ชัดเจนที่กล่าวถึงในสเปคใด ๆ ยังคงมีความแตกต่างโดยนัยนี้ที่สามารถรองรับด้วยความคลุมเครือบางอย่าง ภาษานั้นต้องสนับสนุนstringในลักษณะที่การนำไปปฏิบัติไม่ได้ (ค่อนข้าง) จึงจำเป็นต้องพิจารณาสำหรับชั้นเรียนพิเศษใน BCL
Kirk Woll

106
@ KirkWoll: ตามข้อกำหนดภาษาภาษานั้นจะต้องพิจารณาstringว่าเป็นประเภทเดียวกับ BCL System.Stringทุกประการ ที่ไม่คลุมเครือเลย แน่นอนคุณสามารถใช้คอมไพเลอร์ของคุณเองโดยใช้ไวยากรณ์ C # และใช้โทเค็นทั้งหมดที่พบเช่นนั้นสำหรับบางสิ่งตามอำเภอใจโดยไม่เกี่ยวข้องกับสิ่งที่กำหนดไว้ในข้อกำหนดภาษา C # อย่างไรก็ตามภาษาที่ได้จะมีลักษณะคล้าย C # เท่านั้นไม่สามารถพิจารณา C # ได้
หรือผู้ทำแผนที่

88
คุณสามารถใช้stringโดยไม่ต้องใช้คำสั่งสำหรับระบบ Stringคุณไม่สามารถทำเช่นนั้นด้วย
Wilsu

14
สำหรับคนที่มาจาก Algol และ Fortran, stringการสนทนานี้แสดงให้เห็นว่ามีสิ่งผิดปกติกับ มันเป็นสิ่งจำเป็นที่จะย่อSystem.Stringแต่เป็นนามแฝงดูเหมือนว่าค่อนข้าง แต่ไม่ใช่สิ่งเดียวกัน หลังจากหลายปีของ C # แต่ผมว่ามันมีความปลอดภัยที่จะเพียงแค่ใช้stringและไม่ต้องกังวลเกี่ยวกับstring.Format() System.String
Roland

8
@Sangeeta คุณกำลังพูดอะไร System.Stringระดับยังคงมีอยู่และstringคำหลักยังคงเป็นนามแฝงสำหรับมัน เช่นเดียวกับและSystem.Int32 intพวกเขาเป็นสิ่งเดียวกันอย่างแท้จริง
Craig

คำตอบ:


6104

stringเป็นนามแฝงใน C # System.Stringสำหรับ
ดังนั้นทางเทคนิคจึงไม่มีความแตกต่าง มันเหมือนเทียบกับint System.Int32

ตามแนวทางแล้วเราแนะนำให้ใช้stringทุกครั้งที่คุณอ้างถึงวัตถุ

เช่น

string place = "world";

ในทำนองเดียวกันฉันคิดว่าโดยทั่วไปจะแนะนำให้ใช้Stringหากคุณต้องการอ้างอิงเฉพาะชั้นเรียน

เช่น

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

นี่คือสไตล์ที่ไมโครซอฟท์มีแนวโน้มที่จะใช้งานในตัวอย่างของพวกเขา

ปรากฏว่าคำแนะนำในพื้นที่นี้อาจมีการเปลี่ยนแปลงเนื่องจากขณะนี้StyleCopบังคับใช้การใช้ชื่อแทนเฉพาะ C #


163
หากคุณตัดสินใจที่จะใช้ StyleCop และทำตามนั้นจะเป็นการใช้ประเภทเฉพาะกับภาษานั้น ๆ ดังนั้นสำหรับ C # คุณจะมีสตริง (แทนที่จะเป็น String), int (แทน Int32), float (แทน Single) - stylecop.soyuz5.com/SA1121.html
Dominic Zukiewicz

144
ฉันใช้นามแฝงอยู่เสมอเพราะฉันคิดว่าสักวันมันอาจจะมีประโยชน์เพราะพวกเขาทำตัวเป็นนามธรรมดังนั้นจึงสามารถทำให้การใช้งานของพวกเขาเปลี่ยนไปโดยที่ฉันไม่รู้
Rob

37
Visual Studio 2015 กล่าวว่า String รูปแบบควรเปลี่ยนเป็น string รูปแบบดังนั้นฉันเดาว่า Microsoft กำลังดำเนินการเช่นนั้น ฉันมักจะใช้ String สำหรับวิธีการคงที่
Sami Kuhmonen

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ตัวอักษรและมีชื่อแทนด้วย)

มีสถานการณ์หนึ่งที่คุณต้องใช้นามแฝงคือ: เมื่อระบุประเภทพื้นฐานของ enum อย่างชัดเจน ตัวอย่างเช่น

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

นั่นเป็นเพียงเรื่องของวิธีการที่กำหนดสเป็ค enum ประกาศ - ส่วนที่อยู่หลังลำไส้ใหญ่จะต้องมีหนึ่งประเภทการผลิตซึ่งเป็นหนึ่งในสัญลักษณ์ของ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 ของข้อมูลจำเพาะ (ฉันไม่สามารถพูดที่นี่ได้อย่างง่ายดายเพราะมันยาวเกินไป) มันไม่ชัดเจนบอกว่าคุณได้มีการใช้นามแฝง แต่นามแฝงที่มีการจัดเรียงของถือว่าเป็นประเภทของตัวเอง มันแปลกไปหน่อย
Jon Skeet

32
@PiPeep สิ่งที่น่าประหลาดใจยิ่งกว่าจำนวน upvotes มากคือ downvote ในปริมาณต่ำ (พิจารณา 5 อันดับแรกของโพสต์มีจำนวน upvotes มากกว่า 2000 และยังมี downvote เพียง 1 อันเท่านั้น) โดยเฉพาะอย่างยิ่งเมื่อคุณคำนึงถึงความคิดเห็นว่ามี "ผู้เกลียดชัง" อยู่เสมอในชุมชนใด ๆ ฉันพบว่ามันยอดเยี่ยมจริงๆ
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ตัวระบุที่ไม่ใช่คำหลัก
Sanjeev Rai

33
@SanjeevRai: ใช่ คุณสามารถใช้@stringเพื่อสร้างตัวระบุที่ลงท้ายstringด้วย มันเป็นกลไกการหลบหนี
Jon Skeet

715

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 อย่างต่อเนื่องเพราะเป็นภาษาที่ไม่รู้และเป็นประเภทที่เห็นได้ชัดเป็นอิสระจากภาษาใด ๆ
ปีเตอร์ - Reinstate Monica

5
@ Nyerguds มีสองเหตุผลที่ไม่ต้องกังวลกับมัน หนึ่งคือที่intกำหนดไว้ในข้อมูลจำเพาะภาษา C # เป็นจำนวนเต็ม 32 บิตโดยไม่คำนึงถึงฮาร์ดแวร์ C # แม้จะมีมรดกร่วมกันในสายหมอกแห่งกาลเวลา แต่จริงๆแล้วไม่ใช่การเปลี่ยนintเป็นจำนวนเต็ม 64 บิตจะเป็นการเปลี่ยนแปลงที่ไม่แน่นอนในข้อกำหนดและภาษา มันจะต้องกำหนดใหม่longตามที่longเป็นปัจจุบันเป็นจำนวนเต็ม 64 บิต เหตุผลอื่นที่ไม่ต้องกังวลนั้นไม่เกี่ยวข้องเนื่องจากประเภทจะไม่เปลี่ยนแปลง แต่ .NET เป็นเพียงนามธรรมพอที่ 99% ของเวลาที่คุณไม่ต้องคิดเกี่ยวกับเรื่องนี้อยู่แล้ว ;-)
Craig

5
@Craig ฉันขุดลงไปในจำนวนมากของรูปแบบเก่าที่เป็นกรรมสิทธิ์ของเกมที่ผมไม่ต้องคิดเกี่ยวกับที่ตลอดเวลาแม้ว่า แล้วใช้Int16, Int32และInt64เป็นจำนวนมากโปร่งใสมากขึ้นในรหัสกว่าการใช้ nondescriptive ค่อนข้างshort, intและlong
Nyerguds

504

คำตอบที่ดีที่สุดที่ฉันเคยได้ยินเกี่ยวกับการใช้นามแฝงประเภทที่ระบุไว้ใน C # มาจากเจฟฟรีย์ริกเตอร์ในหนังสือของเขาCLR ผ่าน C # นี่คือเหตุผล 3 ข้อของเขา:

  • ฉันเห็นนักพัฒนาจำนวนหนึ่งสับสนโดยไม่รู้ว่าจะใช้สตริงหรือสตริงในรหัสของพวกเขาหรือไม่ เนื่องจากใน 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

ดังนั้นคุณมีมัน ฉันคิดว่าสิ่งเหล่านี้เป็นจุดที่ดีจริงๆ อย่างไรก็ตามฉันไม่พบว่าตัวเองใช้คำแนะนำของ Jeffrey ในรหัสของฉันเอง บางทีฉันอาจติดอยู่ในโลก C # ของฉัน แต่ท้ายที่สุดฉันพยายามทำให้โค้ดของฉันดูเหมือนโค้ดเฟรมเวิร์ก


24
จุดที่สองเสียงจริงเช่นเหตุผลไม่ได้กับการใช้งานstring, intฯลฯ
MauganRa

15
@MauganRa และมันควรจะเป็นผู้เขียนหนังสือแสดงเหตุผลเหล่านั้นว่าทำไมเขาถึงไม่ใช้นามแฝง
tomi.lee.jones

31
"ถ้ามีคนกำลังอ่านซอร์สโค้ด C # พวกเขาควรแปลความยาวตามสเป็คภาษาไม่ใช่สเป็คภาษาอื่น" นั่นคือจุดที่ขาดหายไปอย่างสิ้นเชิง ไม่ใช่ว่าทุกคนตั้งใจที่จะตีความรหัสผิดมันเป็นเรื่องง่ายที่สมองของคนจะข้ามไปสู่ข้อสรุปที่ผิดเมื่อประเภทมีความหมายแตกต่างจากสิ่งที่โปรแกรมเมอร์เห็นในชีวิตประจำวันในบริบทอื่น เราทุกคนทำผิดพลาด การใช้ประเภทที่มีชื่ออย่างชัดเจนจะทำให้ข้อผิดพลาดเหล่านั้นมีโอกาสน้อยลง
ดาร์ริล

10
+ เหตุผลเหล่านี้สรุปความรู้สึกของฉันในเรื่องนี้ เมื่อฉันเริ่มเขียนโค้ดใน C # เป็นครั้งแรก (มาจากพื้นหลัง Java / C ++ / C) ฉันคิดว่าชื่อแทนน่าเกลียด ฉันยังคงรู้สึกอย่างนั้นโชคไม่ดีที่โลกส่วนใหญ่ไม่เห็นด้วยกับฉันหรือพวกเขาไม่สนใจและใช้ตัวพิมพ์เล็ก
gusgorman

8
@ Jinzai คำถามเกี่ยวกับ C # ซึ่งlongถูกกำหนดเป็นจำนวนเต็ม 64 บิตที่ลงนามโดยไม่คำนึงถึงแพลตฟอร์มหรือคอมไพเลอร์ ดังนั้นในบางกรณีอย่างน้อยใช่มันไม่ขึ้นอยู่กับภาษา
phoog

455

stringเป็นคำที่สงวนไว้ แต่Stringเป็นเพียงชื่อคลาส หมายความว่าstringไม่สามารถใช้เป็นชื่อตัวแปรได้

หากด้วยเหตุผลบางประการที่คุณต้องการตัวแปรชื่อstringคุณจะเห็นเฉพาะการคอมไพล์แรกเหล่านี้:

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

หากคุณต้องการชื่อตัวแปรที่ชื่อว่าstringคุณสามารถใช้@เป็นคำนำหน้า:

StringBuilder @string = new StringBuilder();

ความแตกต่างที่สำคัญอื่น: Stack Overflow จะเน้นให้เห็นถึงความแตกต่าง


20
โปรดทราบว่าการโทรในพื้นที่@stringนั้นไม่มีประโยชน์จริงๆเนื่องจากชื่อของคนในท้องถิ่นนั้นมีอยู่ใน PDB เท่านั้น อาจจะเรียกมัน_stringหรืออะไรก็ได้ มันทำให้รู้สึกมากขึ้นสำหรับสิ่งที่มีชื่อเข้าถึงได้ผ่านทางภาพสะท้อนที่ชื่อของนั้นสมาชิกจะ@string "string"
Roman Starkov

25
โปรดทราบว่าการใช้คำที่สงวนไว้เป็นชื่อตัวแปรนั้นไม่เหมาะสมอย่างยิ่ง
Elton

7
OP ไม่ต้องการใช้สตริงหรือสตริงเป็นชื่อตัวแปร พวกเขาถามสำหรับคำอธิบายของความแตกต่างระหว่างทั้ง ๆประเภท คำตอบของคุณให้บริการเพื่อเพิ่มความสับสนมากขึ้น IMO
Matt Wilko

1
@craig ถ้าคุณเขียนซอฟต์แวร์เพื่อสอนผู้คนถึงวิธีผูกปม?
Simon_Weaver

5
@Simon_Weaver เป็นกลุ่มนอต? ฮ่าฮ่าดี :-) แน่นอนคุณสามารถเลือกชื่ออื่นเช่นชุดข้อความ เดี๋ยวก่อนนะเดี๋ยวก่อน!
Craig

391

มีข้อแตกต่างประการหนึ่งคือคุณไม่สามารถใช้งานได้Stringโดยไม่using System;ได้ตั้งใจ


14
โดยค่าเริ่มต้นคนส่วนใหญ่จะเพิ่มสิ่งนี้ในรูปแบบใด ๆ ที่ด้านบนของไฟล์ VS ทำสิ่งนี้ตามค่าเริ่มต้นในกรณีส่วนใหญ่ไม่ใช่ทั้งหมด!
IbrarMumtaz

9
ตามค่าเริ่มต้นฉันจะเพิ่มเฉพาะusingข้อความที่ฉันต้องการและลบสิ่งที่ไม่ต้องการออกอย่างชัดเจน เครื่องมือเพิ่มประสิทธิภาพการผลิตไฟฟ้า> "[x] ลบและจัดรูปแบบการใช้งานเมื่อบันทึก"
JMD

2
@JMD ฉันได้แก้ไขไฟล์เทมเพลต. cs ดังนั้นมันจึงไม่มีคำสั่งการใช้งานที่ด้านบน! internal sealedผมก็เปลี่ยนแม่แบบชั้นเรียนเพื่อ
ErikE

@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
เพียงเลือกหนึ่งอันและสอดคล้องกัน หากคุณทำงานที่ไหนสักแห่งที่มีสไตล์บ้านให้ใช้มัน
Alan B

3
สไตล์น่าเสียดายคือความชอบส่วนบุคคลและอาจแพงเกินไปที่จะบังคับใช้ในรหัสฐานขนาดใหญ่ในหลาย ๆ ทีมโดยไม่มีเจ้าของรหัสเฉพาะ มีเรื่องที่สำคัญกว่าที่จะดูแลมากกว่า string vs String เสมอ ซึ่งนำเรากลับไปสู่ ​​"สิ่งที่สำคัญยิ่งกว่าในชีวิต"
aiodintsov

นี่คือสิ่งที่ชอบแน่นอน ตัวอย่างเช่น: ฉันชอบที่จะใช้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 (สตริง) โดยส่วนตัวแล้วฉันคิดว่าฉันเขียน C # (และเป็น C # ที่ใช้. NET)
bytedev

7
@Alex: จุดของฉันเป็นเพียงที่ฉันชอบที่จะเฉพาะเจาะจงมากในการเขียนโปรแกรมของฉันเพื่อที่จะลบความกำกวม
NotMe

22
ในส่วนอื่น ๆ ที่แน่นอนของสเปกตรัมของฉันเกือบตลอดเวลาเพียงแค่ใช้var
Tic

192

stringและStringเหมือนกันทุกวิธี (ยกเว้นตัวพิมพ์ใหญ่ "S") ไม่มีนัยยะทางประสิทธิภาพ

ตัวพิมพ์เล็กstringเป็นที่ต้องการในโครงการส่วนใหญ่เนื่องจากการเน้นไวยากรณ์


Jeffrey Richter แนะนำให้ใช้ประเภท CLR ในทุกกรณี (CLR ผ่าน C #) เพื่อหลีกเลี่ยงความสับสนที่เกิดขึ้นที่นี่
Josh

เห็นได้ชัดว่าคุณใช้ S หรือ s มันจะทำให้เกิดคำถามนี้ดังนั้นลงคะแนนริกเตอร์ ;)
แบรดวิลสัน

Richter หมายความว่าสตริงนั้นไม่ควรเป็นตัวเลือก - Microsoft ไม่ควรใช้มันในภาษา คุณไม่สามารถลงคะแนนผู้ตัดสิน - เขาเป็นตำนาน! :)
Joe Ratzer

1
ฉันยอมรับว่ามันอาจจะดีกว่าถ้าไม่มีนามแฝงเลย แต่เนื่องจากว่าเรามีพวกเขาฉันคิดว่ามันดีที่จะใช้พวกมัน (แต่ไม่ใช่ในชื่อเมธอดและอื่น ๆ )
Jon Skeet

10
"string" ไม่เหมือนกับ "String" หมายถึง "System.String" ดังนั้นถ้าคุณใช้ "String" คุณต้องใส่ "using System" เพื่อรวม namespace
ThiagoAlves

185

C # เป็นภาษาที่ใช้ร่วมกับ CLR

string เป็นประเภทใน C #

System.String เป็นประเภทใน CLR

เมื่อคุณใช้ C # ร่วมกับการ CLR จะถูกแมปไปstringSystem.String

ในทางทฤษฎีคุณสามารถใช้ C # -compiler ที่สร้าง Java bytecode การดำเนินการที่เหมาะสมของคอมไพเลอร์นี้อาจจะ map stringไปjava.lang.Stringเพื่อที่จะทำงานร่วมกับห้องสมุดรันไทม์ Java


1
stringไม่ใช่ประเภทใน C #; มันเป็นคำที่สงวนไว้ซึ่งแมปกับประเภทใน CLR
CesarGon

@CesarGon: ตาม ECMA-334, ส่วน 8.2.1: "C # ให้ชุดประเภทที่กำหนดไว้ล่วงหน้า [... ] ประเภทการอ้างอิงที่กำหนดไว้ล่วงหน้าคือวัตถุและสตริง"
Rasmus Faber

10
ตามที่ ECMA-334 มาตรา 9.4.3 "สตริง" เป็นคำหลัก :-) ฉันเห็นด้วยกับคุณว่า "สตริง" เป็นประเภทถ้าคุณมุ่งเน้นไปที่ความหมาย แต่ฉันจะบอกว่ามันเป็นคำหลัก (เช่นคำที่สงวนไว้) ถ้าคุณมุ่งเน้นไปที่ไวยากรณ์ มาตรฐานด้านหลังของทั้งสองมุมมอง (อาจจะคลุมเครือเกินไป!) สำหรับฉัน OP เป็นเรื่องเกี่ยวกับไวยากรณ์ดังนั้นฉันมักจะมุ่งเน้นไปที่ไวยากรณ์เมื่อฉันดูคำตอบ แต่ฉันก็เห็นประเด็นของคุณเช่นกัน นอกจากนี้คำตอบของคุณอาจตีความได้ว่าหมายความว่ามีสองประเภทที่แตกต่างกัน: 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 # อื่นดังที่แสดงด้านล่าง: -

วัตถุ: System.Object, สตริง: System.String, บูล: System.Boolean, ไบต์: System.Byte, sbyte:, System.SByteสั้น: System.Int16และอื่น ๆ

ตอนนี้คำถามล้านดอลลาร์จากมุมมองของโปรแกรมเมอร์ดังนั้นเมื่อใดควรใช้ "String" และ "string"

สิ่งแรกที่ควรหลีกเลี่ยงความสับสนใช้หนึ่งในนั้นอย่างสม่ำเสมอ แต่จากมุมมองแนวปฏิบัติที่ดีที่สุดเมื่อคุณประกาศตัวแปรเป็นเรื่องดีที่จะใช้ "string" (small "s") และเมื่อคุณใช้มันเป็นชื่อคลาสแล้วต้องการสตริง "String" (ตัวพิมพ์ใหญ่ "S")

ในรหัสด้านล่างด้านซ้ายมือเป็นการประกาศตัวแปรและมันประกาศโดยใช้ "สตริง" ที่ด้านขวามือเรากำลังเรียกใช้เมธอดดังนั้น "String" จึงมีเหตุผลมากขึ้น

string s = String.ToUpper() ;

25
"ในระยะสั้น" สตริง "เป็นนามแฝง (สิ่งเดียวกันกับชื่อที่แตกต่างกัน) ของ" สตริง "" สิ่งนี้ไม่ถูกต้อง: alias คือ "string"
Xavier Egea

3
เมื่อคุณประกาศตัวแปรเป็นเรื่องดีที่จะใช้ "string" (small "s") และเมื่อคุณใช้มันเป็นชื่อคลาสแล้วต้องการ "String" (ตัวพิมพ์ใหญ่ "S") ดูเหมือนว่าการประชุมนี้จะไม่ถูกต้องอีกต่อไป: ถ้าคุณใช้ Visual Studio 2015 และพยายามเขียนStringแนะนำให้คุณ "ลดความซับซ้อนของรหัสของคุณ" ให้ถือstring...
Massimiliano Kraus

165

กรณีที่ต่ำกว่าเป็นนามแฝงสำหรับstring พวกเขาเป็นในแบบเดียวกันSystem.StringC#

มีการถกเถียงกันว่าคุณควรใช้ประเภทของระบบ (เป็นSystem.Int32, System.Stringฯลฯ ) ประเภทหรือC# aliases( int, stringฯลฯ ) ฉันเองเชื่อว่าคุณควรใช้C# aliasesแต่เป็นเพียงความชอบส่วนตัวของฉัน


4
นั่นเป็นปัญหาพวกเขาไม่ใช่นามแฝง 'C #' แต่เป็นนามแฝง 'C' ไม่มี 'สตริง' ดั้งเดิมหรือ 'int' ในภาษา C # เพียงแค่น้ำตาลประโยค
Quarkly

16
ไม่แน่ใจว่ามาจากที่นี่ที่ใด "C" เนื่องจากข้อกำหนดคุณสมบัติภาษา C # 5 อ่าน "สตริงคำหลักเป็นเพียงนามแฝงสำหรับคลาส System.String ที่กำหนดไว้ล่วงหน้า" ในหน้า 85 วรรค 4.2.4 ภาษาระดับสูงทั้งหมดเป็นน้ำตาลประโยคผ่านชุดคำสั่ง CPU และ bytecode
aiodintsov

156

stringSystem.Stringเป็นเพียงนามแฝงสำหรับ คอมไพเลอร์จะปฏิบัติต่อพวกเขาเหมือนกัน

เฉพาะที่แตกต่างในทางปฏิบัติจะเน้นไวยากรณ์ที่คุณกล่าวถึงและที่คุณต้องเขียนถ้าคุณใช้using SystemString


คุณไม่จำเป็นต้องนำหน้าระบบเพื่อใช้งาน String
Joe Ratzer

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เป็นเพียงตัวระบุทั่วไปที่สามารถอ้างถึงอะไรก็ได้ ทั้งนี้ขึ้นอยู่กับสมาชิกของชนิดปัจจุบัน namespace ปัจจุบันและการประยุกต์ใช้usingคำสั่งและตำแหน่งของพวกเขาอาจจะเป็นค่าหรือชนิดที่แตกต่างจากStringglobal::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ในบริบทอื่น ๆ ที่ประเภทเป็นไปได้เพียงอย่างเดียว syntactically ตัวอย่างเช่นString local = "Hi mum!";อาจตกลง (ขึ้นอยู่กับเนมสเปซและusingคำสั่ง)

ที่เลวร้ายยิ่ง: บอกว่าString.Concat(someSequence)จะมีแนวโน้มที่ (ขึ้นอยู่กับusings) 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; แล้วนับข้อบกพร่อง
Steve

7
นี่คือคำตอบที่ถูกต้อง เป็นstring อาจเป็นอะไรก็ได้ System.StringString
Dave Cousineau

ตกลง @DaveCousineau - นั่นคือจุดของนามแฝง คุณสามารถสร้างStringประเภทอื่นที่จะไม่ถูกตั้งค่าเป็นวัตถุ System.String ตรวจสอบที่: blog.paranoidcoding.com/2019/04/08/…
Kristopher

"คำสำคัญstringมีความหมายที่เป็นรูปธรรมใน C # มันเป็นประเภทSystem.Stringที่มีอยู่ในคอร์รันไทม์แกนหลักรันไทม์เข้าใจในประเภทนี้และให้ความสามารถที่นักพัฒนาคาดหวังstringsใน. NET การมีอยู่นั้นสำคัญมากสำหรับ C # คอมไพเลอร์จะไม่มีอยู่ก่อนที่จะพยายามแยกบรรทัดของโค้ดดังนั้นจึงstringมีความหมายที่แม่นยำและชัดเจนในรหัส C # ตัวระบุStringแม้ว่าจะไม่มีความหมายที่เป็นรูปธรรมใน C # มันเป็นตัวบ่งชี้ที่ผ่านกฎการค้นหาชื่อทั้งหมด เช่นWidget, Studentฯลฯ … "
Kristopher



87

กับสิ่งที่ดูเหมือนจะเป็นเรื่องธรรมดาในหมู่โปรแกรมเมอร์คนอื่น ๆ ฉันชอบStringมากกว่าstringเพียงเพื่อเน้นความจริงที่Stringเป็นประเภทอ้างอิงตามที่ Jon Skeet กล่าวถึง



78

ฉันแค่ต้องการเพิ่มสิ่งนี้ลงในคำตอบ lfousts จากหนังสือ Ritchers:

สถานะข้อมูลจำเพาะภาษา C #“ ในเรื่องของสไตล์การใช้คำหลักได้รับความนิยมมากกว่าการใช้ชื่อประเภทระบบที่สมบูรณ์” ฉันไม่เห็นด้วยกับข้อกำหนดภาษา ฉันชอบใช้ชื่อประเภท FCL และหลีกเลี่ยงชื่อประเภทดั้งเดิม ในความเป็นจริงฉันต้องการให้คอมไพเลอร์ไม่ได้เสนอชื่อดั้งเดิมและบังคับให้ผู้พัฒนาใช้ชื่อประเภท FCL แทน นี่คือเหตุผลของฉัน:

  • ฉันเห็นนักพัฒนาจำนวนหนึ่งสับสนโดยไม่รู้ว่าจะใช้สตริง หรือสตริงในรหัสของพวกเขาหรือไม่ เนื่องจากใน C # string (คำหลัก) จะจับคู่กับ 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 # -isms จะคืบคลานเข้าไปในรหัสไลบรารีคลาส ยกตัวอย่างเช่นไมโครซอฟท์ FCL ถูกเขียนเกือบเฉพาะใน C # และนักพัฒนาในทีม FCL ได้แนะนำตอนนี้วิธีการเข้าไปในห้องสมุดเช่น อาร์เรย์ ‘s GetLongLengthซึ่งส่งกลับInt64ค่าที่เป็นเวลานานใน C # แต่ไม่ได้อยู่ในภาษาอื่น ๆ (เช่น C ++ / CLI) อีกตัวอย่างหนึ่งคือวิธีLongCountของ System.Linq.Enumerable

ฉันไม่ได้รับความเห็นของเขาก่อนที่จะอ่านย่อหน้าที่สมบูรณ์


72

String ( System.String) เป็นคลาสในไลบรารีคลาสฐาน 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 ของ Ritchie สำหรับฉันแล้วมันก็สมเหตุสมผลที่ CLR ทุกภาษาจะต้องสามารถรองรับชุดประเภท CLR ได้ดังนั้นการใช้ประเภท CLR ด้วยตัวคุณเองนั้นจะให้รหัสที่ชัดเจนยิ่งขึ้นและอาจเป็นรหัส "ที่ใช้ซ้ำได้"

ตอนนี้ฉันทำมาหลายปีแล้วมันก็เป็นนิสัยและฉันชอบสีที่ VS แสดงให้เห็นถึงประเภท CLR

Downer จริงเพียงอย่างเดียวคือการเติมข้อมูลอัตโนมัติใช้ประเภท C # ดังนั้นฉันเลยพิมพ์ใหม่ที่สร้างขึ้นโดยอัตโนมัติเพื่อระบุประเภท CLR แทน

นอกจากนี้ตอนนี้เมื่อฉันเห็น "int" หรือ "string" ดูเหมือนว่าฉันผิดจริงๆเช่นฉันกำลังดูรหัส C ของปี 1970


49

ไม่มีความแตกต่าง

คีย์เวิร์ด C # stringจะจับคู่กับประเภท. NET System.String- เป็นนามแฝงที่ใช้ในการตั้งชื่อภาษา

ในทำนองเดียวกันแมปไปintSystem.Int32


ในบิลด์ 64 บิต, int แมปไปที่ System.Int64 (8 ไบต์), ใน 32 บิตบิลด์แมปไปที่ System.Int32 (4 ไบต์)
Alex

1
IntPtr และ UIntPtr เป็นประเภทเดียวที่เปลี่ยนขนาดตามแพลตฟอร์ม (ไม่คำนึงถึงประเภทตัวชี้ตามจริงเช่นint*และประเภทที่ประกอบด้วย [U] IntPtrs หรือตัวชี้ที่แท้จริง)
Paddy

45

มีคำพูดเกี่ยวกับเรื่องนี้จากหนังสือแดเนียล Solis'

ประเภทที่กำหนดไว้ล่วงหน้าทั้งหมดจะถูกแมปโดยตรงกับประเภท. NET พื้นฐาน ชื่อประเภท C (สตริง) เป็นเพียงนามแฝงสำหรับ. ประเภท NET (สตริงหรือ System.String) ดังนั้นการใช้ชื่อ. NET จะทำงานได้ดีในทาง syntactically แม้ว่าจะไม่ได้รับการสนับสนุนก็ตาม ภายในโปรแกรม C # คุณควรใช้ชื่อ C # แทนชื่อ. NET


41

เชือกเป็นคำหลักและคุณไม่สามารถใช้สตริงเป็นตัวระบุได้

สตริงไม่ใช่คำหลักและคุณสามารถใช้มันเป็นตัวระบุ:

ตัวอย่าง

string String = "I am a string";

คำหลักstring เป็นชื่อแทน System.Stringนอกเหนือจากปัญหาคำหลักคำหลักสองคำนี้เทียบเท่ากันทั้งหมด

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

2
ข้อแตกต่างเล็ก ๆ น้อย ๆ ก็คือถ้าคุณใช้คลาส String คุณจะต้องนำเข้า System namespace ที่ด้านบนของไฟล์ของคุณในขณะที่คุณไม่ต้องทำสิ่งนี้เมื่อใช้คำสำคัญสตริง
Uttam

มีกรณีการใช้งานง่าย ๆ ที่คำสั่งความเท่าเทียมกันจะล้มเหลว ... เช่นการกำหนดประเภทการโทร String ในเนมสเปซ blah และนำเข้าเนมสเปซนั้นลงในไฟล์ที่คำสั่งความเท่าเทียมกันกำลังทำงานอยู่
rick

40

ใช่ว่าเป็นความแตกต่างระหว่างพวกเขาไม่เหมือนและboolBoolean


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ยังหมายถึงนักพัฒนากำลังออกจากโปรแกรมของพวกเขาถึงการตีความในสถานที่ที่มีคำตอบเดียวที่ถูกต้อง เมื่อไม่ผูกกับผิดประเภทก็สามารถปล่อยให้นักพัฒนาแก้จุดบกพร่องสำหรับชั่วโมงยื่นข้อบกพร่องในทีมของคอมไพเลอร์และโดยทั่วไปจะเสียเวลาที่จะได้รับการบันทึกไว้โดยใช้Stringstring

อีกวิธีในการมองเห็นความแตกต่างคือกับตัวอย่างนี้:

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

หลายคนอาจแย้งว่าในขณะที่ข้อมูลนี้มีความถูกต้องทางเทคนิคการใช้Stringยังคงใช้ได้เพราะมันหายากเหลือเกินที่ฐานรหัสจะกำหนดประเภทของชื่อนี้ หรือว่าเมื่อไหร่Stringมีการกำหนดมันเป็นสัญญาณของรหัสฐานที่ไม่ดี

[ ... ]

คุณจะเห็นว่าStringมีการกำหนดไว้สำหรับวัตถุประสงค์ที่ถูกต้องจำนวนหนึ่ง: ผู้ช่วยเหลือการสะท้อน, ไลบรารีการทำให้เป็นอนุกรม, lexers, โปรโตคอล ฯลฯ ... สำหรับไลบรารีใด ๆ เหล่านี้Stringเทียบกับstringผลที่เกิดขึ้นจริงขึ้นอยู่กับตำแหน่งที่ใช้รหัส

ดังนั้นจำไว้ว่าเมื่อคุณเห็นการStringปะทะกับstringการอภิปรายนี่เป็นเรื่องเกี่ยวกับความหมายไม่ใช่สไตล์ การเลือกสตริงให้ความหมายที่คมชัดกับฐานรหัสของคุณ การเลือกStringนั้นไม่ผิด แต่จะเปิดประตูทิ้งไว้เพื่อความประหลาดใจในอนาคต

หมายเหตุ: ฉันคัดลอก / วางโพสต์บล็อกส่วนใหญ่เพื่อเหตุผลการเก็บถาวร ฉันไม่สนใจบางส่วนดังนั้นฉันแนะนำให้ข้ามและอ่านโพสต์บล็อกหากคุณทำได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.