จุดของคุณสมบัติ string.Empty คืออะไร


35

เหตุใดคุณสมบัติจึงstring foo = string.Emptyรวมอยู่ใน BCL ดูเหมือนว่า verbose มากขึ้นและไม่ชัดเจนกว่าการใช้สตริงว่างเปล่า ( string foo = "")


6
Nitpick: มันไม่ได้เป็นส่วนหนึ่งของภาษา มันเป็นส่วนหนึ่งของ BCL VB.NET และ F # สามารถใช้งานได้เช่นเดียวกับภาษา. NET อื่น ๆ ทั้งหมด
Oded

19
เพราะไม่เช่นนั้นคุณไม่สามารถทำสิ่งชั่วร้ายเช่นtypeof(string).GetField("Empty").SetValue(null, " ");นั้นได้)
Mason Wheeler

1
@MasonWheeler - ความสุขของการสะท้อน สำหรับความชั่วร้ายที่แท้จริงคุณต้องใคร่ครวญใช่มั้ย
Oded

1
@MasonWheeler, +1 โอ้พระเจ้าแว่นตาพวกเขาไม่ทำอะไรเลย!]
Machado

1
@MasonWheeler นั่นคือความชั่วร้ายบริสุทธิ์กลั่น ฉันรักสิ่งนี้. คำถามหากคุณสนใจ: มันจะปลอดภัยกว่า (และนักแสดงที่เหมาะสม) ที่จะเขียนเป็นpublic static string Empty { get { return string.Intern(""); } }?
เจสซีซี. เครื่องตัด

คำตอบ:


55

ฉันเดาได้เฉพาะที่นี่:

string.Emptyได้รับการกำหนดไว้สำหรับ explicitness - เมื่อเริ่มต้นสตริงมันอาจไม่ชัดเจนจากบริบทที่""มีความหมายอย่างชัดเจนว่าเป็น initializer (แทนnullหรือพูด" "หรือเพียงแค่เป็นเจ้าของสถานที่ในระหว่างการทดสอบ) การใช้string.Emptyเป็นคำตอบที่แน่นอนสำหรับปริศนาประเภทนั้น

นอกจากนี้ยังอาจเป็นการโยนกลับไปที่ C - สตริงว่างใน C ไม่ใช่สตริงว่าง เป็นอาร์เรย์อักขระที่มีอักขระตัวแรกเป็น null (ดังนั้นว่างเปล่า) ซึ่งไม่เหมือนกับ C # จุดของฉันที่นี่เป็นที่ในภาษาที่แตกต่างกันคุณจะเป็นตัวแทนของสตริงที่ว่างเปล่าในรูปแบบที่แตกต่างกัน (และพวกเขาอาจจะมีความหมายที่แตกต่างกัน) - มีstring.Emptyติ๊ดคลุมเครือดังกล่าว

เมื่อเทียบกับสิ่งที่คนอื่นพูดเกี่ยวกับวัตถุหลายรายการ - นี่ไม่ใช่ปัญหาเนื่องจากตัวอักษรสตริงใด ๆ จะได้รับการฝึกงานในการรวบรวม ซึ่งรวมถึงค่าของ-string.Empty ""เมื่อใดก็ตามที่สิ่งเหล่านี้ซ้ำแล้วซ้ำอีกในรหัสวัตถุจะถูกดึงจากสระว่ายน้ำฝึกงาน นี่คือความจริงต่อโดเมนแอป


5
+1 เนื่องจากเป็นคำตอบที่ถูกต้องเท่านั้น
psr

บางภาษาอาจไม่ได้มีตามตัวอักษรสตริงที่ว่างเปล่า เห็นได้ชัดว่าPascalมาตรฐานไม่ได้
dan04

2
"สตริงว่างใน C ไม่ใช่สตริงว่าง" - แต่ถ้าคุณเขียน""คุณจะได้รับ{'\0'}ดังนั้นจะไม่มีความแตกต่างระหว่างสตริงว่างตามตัวอักษรและวิธีการกำหนดวงเวียนอื่น ๆ
Detly

14

ฉันไม่แน่ใจ 100% ของแหล่งข้อมูลที่ฉันได้เรียนรู้สิ่งเหล่านี้ แต่บางจุดของการใช้มันรวมถึง:

  • แต่ละสตริงในแอสเซมบลี. NET จะไม่ซ้ำกันดังนั้นจึงมี

    string foo = "";
    string bar = "";

    ส่งผลให้ 2 สายในการประกอบการส่งออกเนื่องจากสตริงจะไม่เปลี่ยนรูป การอ้างอิงทั้งสองแบบstring.Emptyช่วยลดขนาดชุดประกอบ

  • การชัดแจ้ง เมื่อคุณเจอstring.Emptyเจตนาที่ชัดเจนว่ามันควรจะเป็นสตริงที่ว่างเปล่า แต่ถ้าคุณเจอfoo = ""โปรแกรมเมอร์ไม่ได้ลบเนื้อหาของสตริงในขณะที่ทดสอบและลืมที่จะเพิ่มกลับหรือมันควรจะเป็นอย่างนั้น?

1
ดูเหมือนว่ามันจะเป็นพฤติกรรมที่แปลกสำหรับมันเพื่อเก็บสองสายเหมือนกันในหน่วยความจำ ในความเป็นจริงสิ่งที่จะทำ?
Rig

36
ในความเป็นจริงแล้วสิ่งที่ตรงกันข้ามจะทำ - เรียกว่าการฝึกงานแบบสตริง (แม่นยำกว่าการฝึกงานตัวอักษร) ฉันรู้ว่ามันทำใน Java และ Python และฉันค่อนข้างแน่ใจว่ามันเป็นกรณีในภาษา. NET ด้วย แน่นอนมันสามารถเกิดขึ้นได้ที่ขอบเขตของหน่วยการแปลเดียวดังนั้นหากตัวโหลดแบบไดนามิกรวมข้อมูลดังกล่าวไว้คุณอาจจบลงด้วยสตริงว่างหนึ่งอันต่อไฟล์โปรแกรม ยังไม่มากนัก

9
@delnan ถูกต้องอย่างแน่นอน ""/ string.Emptyมีการฝึกงานและมีเพียงหนึ่งวัตถุจะถูกสร้างขึ้น
Oded

11
@Andy - ตัวอักษรสตริงทั้งหมดจะถูกฝึกงานใน. NET ไม่ใช่ทุกสาย สตริงที่สร้างโดยทางโปรแกรมไม่ได้รับการฝึกงานโดยค่าเริ่มต้น ดูString.Internบน MSDN
Oded

3
@Oded et alia: ที่จริงแล้วไม่มีพวกคุณคนใดที่เหมาะสม ครั้งแรกที่ได้รับการฝึกงานตัวอักษรที่อยู่ในการชุมนุมแต่ไม่จำเป็นต้องข้ามประกอบ ที่สองไม่ว่าสตริงว่างจะถูก interned ข้ามชุดประกอบเป็นรายละเอียดการใช้งานหรือไม่ CLR บางเวอร์ชันทำและบางอันทำไม่ได้ มีลิงก์ไปยังบทความของฉันเกี่ยวกับข้อเท็จจริงนี้ในหนึ่งในคำตอบอื่น ดูรายละเอียด
Eric Lippert

2

string.Emptyไม่มีวัตถุจะถูกสร้างขึ้นสำหรับ การใช้""จะสร้างวัตถุที่น่าจะมาจากกลุ่มนักศึกษาฝึกงานมากที่สุด

ในอดีตผู้คนมีการทดสอบและString.Emptyออกมาเร็วขึ้นเล็กน้อย แต่เป็นการเพิ่มประสิทธิภาพขนาดเล็ก

String.Empty คือสิ่งนี้:

//The Empty constant holds the empty string value.   
//We need to call the String constructor so that the compiler doesn't mark 
//this as a literal.   
//Marking this as a literal would mean that it doesn't show up as a field 
//which we can access from native.  
public static readonly String Empty = ""; 

2
ดังนั้นประเด็นของคุณคือ ...

1
จุดคือ String โดยปกติแล้วค่าคงที่สำหรับ "" ค้นหาผู้แต่ง String.cs เพื่อความหมายที่ลึกซึ้งยิ่งขึ้น :)
Jon Raynor

0

มันเป็นเรื่องของการเพิ่มประสิทธิภาพของการใช้หน่วยความจำและการเพิ่มประสิทธิภาพของการเปรียบเทียบสตริง ทุกครั้งที่คุณใช้สตริงว่างในแอปพลิเคชันของคุณคุณกำลังจัดสรรวัตถุสตริงที่มี 0 ตัวอักษร สำหรับการเปรียบเทียบสตริงสามารถทำได้โดยการเปรียบเทียบการอ้างอิง (พอยน์เตอร์) แทนตัวอักษรโดยตัวละครซึ่งเป็นได้เร็วขึ้นแม้สำหรับสตริงที่ว่างเปล่า

หากคุณใช้สตริงเดียวกันหลายครั้งในแอปพลิเคชันของคุณคุณสามารถใช้กลไกชนิดเดียวกันได้โดยการเรียก String.Intern () กับสตริงของคุณ แต่ถ้าคุณใช้แต่ละสายเพียงครั้งเดียวคุณก็จะใช้หน่วยความจำได้มากกว่าเท่านั้น

ดังนั้น String.Empty เป็นเพียงการเพิ่มประสิทธิภาพกรณีพิเศษซึ่งคุ้มค่าที่จะทำสำหรับแอปพลิเคชั่น. Net ส่วนใหญ่นั่นคือสาเหตุที่มันถูกรวมเข้ากับ BCL

สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับเรื่องนี้ผมขอแนะนำให้อ่านบล็อกโพสต์เอริค Lippert ของ

คุณควรดูเอกสารนี้อ้างอิงโดยโพสต์บล็อกของเขา


4
ลิงก์คำตอบเท่านั้นไม่ได้คำตอบที่ดี หากเอริคจัดโครงสร้างใหม่บล็อกของเขาคำตอบนี้จะไร้ประโยชน์ โปรดสรุปโพสต์ที่นี่เพื่อให้เรามีข้อมูลทั้งหมดที่จะส่ง
ChrisF

7
@ChrisF: ฉันไม่สามารถจัดระเบียบบล็อกใหม่ได้ นั่นจะเป็นการเปลี่ยนแปลงครั้งใหญ่และคุณก็รู้ว่าฉันรู้สึกอย่างไรกับสิ่งเหล่านั้น
Eric Lippert

1
@EricLippert - ฉันรู้ว่าคุณไม่เคยทำแบบนั้น แต่ลิงก์คำตอบเท่านั้นไม่ใช่คำตอบที่ดีและเราจำเป็นต้องสนับสนุนให้ผู้คนตระหนักถึงสิ่งนั้น
ChrisF

3
@EricLippert ไม่เพียง แต่เกี่ยวกับลิงก์ชั่วคราว นอกจากนี้ยังเกี่ยวกับความสุภาพต่อผู้อ่านที่นี่ควรมีเนื้อหาอย่างน้อยในคำตอบโดยตรงเพื่อให้ผู้อ่านสามารถแสดงความคิดเห็นว่าจะติดตามลิงก์หรือไม่ และคำตอบควรสมเหตุสมผลแม้ใน SE ออฟไลน์
Gilles 'หยุดชั่วร้าย'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.