ไม่สามารถใช้ String.Empty เป็นค่าเริ่มต้นสำหรับพารามิเตอร์ที่เป็นทางเลือก


89

ฉันกำลังอ่านC # ที่มีประสิทธิภาพโดย Bill Wagner ในรายการ 14 - ลดลอจิกการเริ่มต้นที่ซ้ำกันเขาแสดงตัวอย่างต่อไปนี้ของการใช้คุณสมบัติพารามิเตอร์ทางเลือกใหม่ในตัวสร้าง:

public MyClass(int initialCount = 0, string name = "")

สังเกตว่าเขาใช้""แทนstring.Empty.
เขาแสดงความคิดเห็น:

คุณจะสังเกตเห็น [ในตัวอย่างด้านบน] ว่าตัวสร้างที่สองระบุ "" สำหรับค่าเริ่มต้นของพารามิเตอร์nameแทนที่จะเป็นแบบธรรมเนียมstring.Emptyพารามิเตอร์มากกว่าจารีตประเพณีมากขึ้นนั่นเป็นเพราะstring.Emptyไม่ใช่ค่าคงที่เวลาคอมไพล์ เป็นคุณสมบัติคงที่ที่กำหนดไว้ในคลาสสตริง เนื่องจากไม่ใช่ค่าคงที่ในการคอมไพล์คุณจึงไม่สามารถใช้เป็นค่าเริ่มต้นสำหรับพารามิเตอร์ได้

หากเราไม่สามารถใช้ไฟล์ string.Emptyแตติกได้ในทุกสถานการณ์นั่นจะไม่ทำให้จุดประสงค์ของมันเสียไปหรือ? ฉันคิดว่าเราจะใช้มันเพื่อให้แน่ใจว่าเรามีวิธีการอ้างถึงสตริงว่างโดยไม่ขึ้นกับระบบ ความเข้าใจของฉันผิดหรือเปล่า? ขอบคุณ.

อัปเดต
เพียงติดตามความคิดเห็น ตาม MSDN:

พารามิเตอร์ทางเลือกแต่ละตัวมีค่าดีฟอลต์เป็นส่วนหนึ่งของนิยาม หากไม่มีการส่งอาร์กิวเมนต์สำหรับพารามิเตอร์นั้นจะใช้ค่าเริ่มต้น ค่าเริ่มต้นต้องเป็นค่าคงที่

จากนั้นเราจะไม่สามารถใช้System.Environment.NewLineอย่างใดอย่างหนึ่งหรือใช้อ็อบเจ็กต์ที่สร้างอินสแตนซ์ใหม่เป็นค่าเริ่มต้น ฉันยังไม่ได้ใช้ VS2010 และมันก็น่าผิดหวัง!


2
ฉันไม่ทราบถึงความแตกต่างระหว่างการแสดงสตริงว่างบนแพลตฟอร์มต่างๆ มันไม่เหมือนนิวไลน์
Tom Cabanski

ใช่ฉันกำลังคิดว่าถ้าอย่างนั้นมันดูดีกว่าในรหัสหรือไม่?
Mikeyg36

1
CLR และไม่ใช่ 'System' เป็นปัจจัยกำหนดว่า "" เป็นสตริงว่างหรือไม่ ดังนั้นฉันคิดว่าคุณสามารถสันนิษฐานได้อย่างปลอดภัยว่า "" เป็นวิธีที่ไม่ขึ้นกับระบบในการอ้างถึงสตริงในการใช้งาน CLR ที่สอดคล้องกัน
Chris Taylor

"ไม่ขึ้นกับระบบ"? เอ้อตรงข้ามกับ "" เฉพาะระบบ? (???)
Qwertie

ตาม MSDN: ค่าของฟิลด์นี้คือสตริงที่มีความยาวเป็นศูนย์ "" ดังนั้นจึงเห็นได้ชัดว่าไม่มีอะไรเกี่ยวข้องกับความเป็นอิสระของแพลตฟอร์มอย่างที่หลายคนชี้ให้เห็น แต่ดูเหมือนคนจะไม่รู้จริงๆว่าทำไมถึงควรใช้!
Mikeyg36

คำตอบ:


66

สำหรับคอมไพเลอร์ C # 2.0 มีประเด็นน้อยมากString.Emptyและในความเป็นจริงในหลาย ๆ กรณีมันเป็นการมองในแง่ร้ายเนื่องจากคอมไพเลอร์สามารถแทรกการอ้างอิงบางส่วนเข้าไปได้""แต่ไม่สามารถทำเช่นเดียวกันกับString.Empty .

ใน C # 1.1 มีประโยชน์ในการหลีกเลี่ยงการสร้างอ็อบเจ็กต์อิสระจำนวนมากทั้งหมดที่มีสตริงว่างเปล่า แต่วันนั้นหายไป ""ใช้งานได้ดี


7
แม้ใน. NET 1.1 มันจะไม่สร้างวัตถุอิสระ "จำนวนมาก" ฉันจำรายละเอียดของความแตกต่างระหว่าง 1.1 และ 2.0 ไม่ได้ในแง่นี้ แต่มันไม่เหมือนกับว่าการอินเทอรัลสตริงถูกนำมาใช้ใน 2.0 เท่านั้น
Jon Skeet

ขอขอบคุณสำหรับการชี้แจง. ฉันได้ดูรอบ ๆ แล้วและยังไม่พบข้อมูลสรุปที่ดีเกี่ยวกับการเปลี่ยนแปลงใน C # 2.0 แม้ว่าฉันจะแน่ใจว่าฉันได้อ่านไปก่อนหน้านี้ ฉันพบคำตอบ StackOverflow จากปี 2008 พร้อมลิงก์ไปยังข้อมูลทางเทคนิคเพิ่มเติม stackoverflow.com/questions/151472/…
Andy Mortimer

1
ฉันจะพยักหน้าให้แม้ว่าฉันไม่ชอบที่จะพูดว่ามีจุดต่อสตริงเล็กน้อยว่างเปล่าเพราะฉันใช้มันค่อนข้างหนัก ฉันคิดว่ามันดูสะอาดกว่าแม้ว่านั่นจะเป็นความคิดเห็นส่วนตัวของฉันก็ตาม มีสตริงหลายแห่งไม่สามารถใช้ว่างได้และฉันไม่มีปัญหาในการใช้ "" ในกรณีเหล่านั้น
xximjasonxx

15
ฉันพบว่ามันง่ายกว่ามากในการระบุสตริงว่างด้วย String ว่างเปล่ากว่าการมองสองครั้งที่ "" เพื่อให้แน่ใจว่าไม่มีเครื่องหมายอะพอสทรอฟีหรืออะไรทำนองนั้นซ่อนอยู่ +1 สำหรับคำอธิบายว่า
NotMe

11
+1 คริส นอกจากนี้ใน VS คุณไม่สามารถค้นหาการใช้งานของ "" ได้ (นอกเหนือจากการค้นหามาตรฐานซึ่งจะนำกลับมาจับคู่ข้อความทั้งหมดรวมถึงความคิดเห็นและมาร์กอัปด้วย) คุณสามารถค้นหาการใช้งานเฉพาะรหัสด้วยสตริงว่างเปล่า
MutantNinjaCodeMonkey

53

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

const string String_Empty = "";

public static void PrintString(string s = String_Empty)
{
    Console.WriteLine(s);
}

[นอกจากเหตุผลหนึ่งที่ชอบ String.Emptyมากกว่า""โดยทั่วไปซึ่งยังไม่ได้กล่าวถึงในคำตอบอื่น ๆ ก็คือมีอักขระ Unicode หลายตัว (ตัวเชื่อมความกว้างศูนย์ ฯลฯ ) ที่มองไม่เห็นด้วยตาเปล่าอย่างมีประสิทธิภาพ ดังนั้นสิ่งที่ดูเหมือน""ไม่จำเป็นต้องเป็นสตริงว่างในขณะที่String.Emptyคุณรู้ว่าคุณกำลังใช้อะไรอยู่ ฉันรับรู้ว่านี่ไม่ใช่แหล่งที่มาของข้อบกพร่องทั่วไป แต่ก็เป็นไปได้]


2
นอกจากนี้ยังมีอักขระตัวระบุที่มองไม่เห็นดังนั้นสิ่งที่ดูเหมือน String_Empty ไม่จำเป็นต้องมี มาตรฐาน Unicode มีบทที่ละเลยส่วนใหญ่เกี่ยวกับการพิจารณาด้านความปลอดภัย
Jim Balter

25

จากคำถามเดิมที่ว่า

ฉันคิดว่าเราจะใช้มันเพื่อให้แน่ใจว่าเรามีวิธีการอ้างถึงสตริงว่างโดยไม่ขึ้นกับระบบ

สตริงว่างสามารถแตกต่างกันไปในแต่ละระบบได้อย่างไร มักจะเป็นสตริงที่ไม่มีอักขระ! ฉันจะจริงๆกลัวถ้าฉันเคยพบการดำเนินงานที่string.Empty == ""กลับเท็จ :) นี่คือไม่ได้Environment.NewLineเช่นเดียวกับสิ่งที่ชอบ

จากโพสต์ค่าหัวของ Counter Terrorist:

ฉันต้องการ String.Empty สามารถใช้เป็นพารามิเตอร์เริ่มต้นในรีลีส C # ถัดไป : ง

นั่นจะไม่เกิดขึ้นอย่างแน่นอน

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

ด้วยstring.Emptyมันเป็นจริงๆไม่มีจุดหมาย - ใช้""จะทำในสิ่งที่คุณต้องการ; มันเป็นเรื่องที่เจ็บปวดที่จะใช้ตัวอักษรสตริง? (ฉันใช้ตัวอักษรทุกที่ - ฉันไม่เคยใช้string.Empty - แต่นั่นเป็นข้อโต้แย้งที่แตกต่างกัน)

นั่นคือสิ่งที่ทำให้ฉันประหลาดใจเกี่ยวกับคำถามนี้ - การร้องเรียนเกี่ยวข้องกับบางสิ่งที่ไม่ได้ทำให้เกิดปัญหาที่แท้จริง สิ่งสำคัญยิ่งกว่าในกรณีที่คุณต้องการให้คำนวณค่าเริ่มต้น ณ เวลาดำเนินการเนื่องจากอาจแตกต่างกันไป ตัวอย่างเช่นฉันสามารถจินตนาการถึงกรณีที่คุณต้องการให้สามารถเรียกใช้เมธอดด้วยDateTimeพารามิเตอร์และตั้งค่าเริ่มต้นเป็น "เวลาปัจจุบัน" ในขณะนี้วิธีแก้ปัญหาที่หรูหราคลุมเครือเพียงอย่างเดียวที่ฉันรู้คือ:

public void RecordTime(string message, DateTime? dateTime = null)
{
    var realDateTime = dateTime ?? DateTime.UtcNow;
}

... แต่นั่นก็ไม่เหมาะสมเสมอไป

สรุปแล้ว:

  • ฉันสงสัยมากว่านี่จะเป็นส่วนหนึ่งของ C #
  • เพราะstring.Emptyมันไม่มีจุดหมายอยู่ดี
  • สำหรับค่าอื่น ๆ ที่ไม่ได้มีค่าเท่ากันเสมอไปอาจเป็นความเจ็บปวด

นี่เป็นวิธีที่ดีในการแก้ไขปัญหา สิ่งเดียวกันนี้สามารถใช้เพื่อดำเนินการ / ตั้งค่าตัวแปรตามอุปกรณ์อื่น ๆ เช่นEnvironment.Newline.. สิ่งเดียวที่ขาดหายไปจากตัวอย่างของคุณคือการตรวจสอบตัวแปรเป็นค่าว่างและส่งข้อยกเว้นกลับไปให้นักพัฒนาโดยบอกเขาว่าแม้ว่าจะเป็นโมฆะ ไม่ยอมรับ. if(dateTime == null){ throw new ArgumentException("The dateTime parameter must be set. Nullable type used for device independent variable set.");}หรืออะไรทำนองนั้น แต่ฉันชอบสิ่งนี้มาก! มีข้อแม้อื่น ๆ ที่จะทำในแบบของคุณหรือไม่?
MaxOvrdrv

@MaxOvrdrv: คุณไม่ต้องการให้มันเป็นโมฆะเป็นข้อผิดพลาดจุดรวมก็คือเมื่อเป็นโมฆะคุณจะคำนวณค่าเริ่มต้น ข้อแม้คือไม่อนุญาตให้ส่งผ่านค่าว่างเป็นค่าที่ถูกต้องในตัวมันเอง
Jon Skeet

คุณพูดถูกอย่างสมบูรณ์เกี่ยวกับเรื่องนี้ ความผิดฉันเอง. - และใช่นั่นจะเป็นข้อแม้ที่แท้จริงเพียงข้อเดียวที่จะไม่ได้ ... นั่นก็ไม่เลวร้ายเกินไป อีกครั้ง: ฉันชอบวิธีนี้มาก! :) ขอบคุณสำหรับการโพสต์! :)
MaxOvrdrv

7

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


2
บางทีอาจช่วยป้องกันความสับสน""และ" "แต่ฉันไม่สามารถพูดได้ว่า" "เป็นเรื่องธรรมดาทั้งหมด
Greg

8
ฉันขอแนะนำว่าใครก็ตามที่ไม่สามารถบอกความแตกต่างระหว่างความต้องการแว่นตาที่ดีกว่าหรือลดความละเอียดของหน้าจอได้ ฉันมีสายตาไม่ดีและจำไม่ได้เลยว่าเคยทำผิดพลาดนั้น (และฉันต้องทำงานกับโค้ดจำนวนมากที่มีทั้งสองอย่างนั้น)
Hans Olsson

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

4

ฉันคิดว่าแนวคิดเบื้องหลังสตริงว่างเปล่ามันช่วยเพิ่มความสามารถในการอ่าน ไม่เหมือนกับการขึ้นบรรทัดใหม่ที่มีความแตกต่างระหว่างการแสดงบนแพลตฟอร์มต่างๆ มันไม่สามารถใช้เป็นพารามิเตอร์เริ่มต้นได้ อย่างไรก็ตามจะไม่ทำให้เกิดปัญหาใด ๆ หากคุณพอร์ตระหว่าง Windows และบางอย่างเช่น Mono บน Linux


5
ฉันคิดว่าคุณคงคิดถูกที่ประเด็นคือบางคนคิดว่าString.Emptyอ่านง่ายกว่า . . โดยส่วนตัวแล้วฉันคิดว่ามันเป็นเรื่องเล็กน้อย ""น่าจะเป็นสตริงที่พบมากที่สุดและทุกคนเคยเห็นมันเป็นพันล้านครั้งแล้วมันจะอ่านไม่ได้อย่างไร? String.Emptyมีประโยชน์ราวกับว่ามีInt32.Zeroไฟล์.
Tim Goodman

3

ในฐานะ FYI ดูเหมือนว่าจะมีการกำหนดข้อ จำกัด เดียวกันกับค่าที่ส่งผ่านไปยังตัวสร้างแอตทริบิวต์ซึ่งต้องเป็นค่าคงที่ เนื่องจาก string.empty ถูกกำหนดให้เป็น:

public static readonly string Empty

ไม่สามารถใช้แทนค่าคงที่จริงได้


2

ฉันใช้string.Emptyเพื่อการอ่านอย่างหมดจด

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

ตัวอย่างเช่น:

if(someString == string.Empty)
{

}

เทียบกับ

if(someString == "")
{

}

ifคำพูดแรกดูเหมือนจะเป็นความตั้งใจและอ่านได้ง่ายกว่าสำหรับฉัน เพราะเป็นเพียงการตั้งค่าแม้ว่าผมไม่เห็นรถไฟชนในการที่จะใช้แทน""string.Empty


-2

บางทีทางออกที่ดีที่สุดสำหรับปัญหานี้คือการใช้วิธีนี้มากเกินไปด้วยวิธีนี้:

public static void PrintString() 
{ 
    PrintString(string.Empty);
}

3
คำตอบของคำถามข้างต้นนั้นเป็นอย่างไร
Pranav Singh

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