เมื่อใดควรใช้ String.Format vs string concatenation


120

ฉันมีโค้ดชิ้นเล็ก ๆ ที่กำลังแยกวิเคราะห์ค่าดัชนีเพื่อกำหนดการป้อนข้อมูลเซลล์ใน Excel มันทำให้ฉันคิด ...

อะไรคือความแตกต่างระหว่าง

xlsSheet.Write("C" + rowIndex.ToString(), null, title);

และ

xlsSheet.Write(string.Format("C{0}", rowIndex), null, title);

คนหนึ่ง "ดีกว่า" หรือไม่? และทำไม?



อาจซ้ำกันได้ของWhy use String.Format?
Druid

คำตอบ:


115

ก่อน C # 6

พูดตามตรงฉันคิดว่าเวอร์ชันแรกนั้นง่ายกว่า - แม้ว่าฉันจะทำให้ง่ายขึ้นเพื่อ:

xlsSheet.Write("C" + rowIndex, null, title);

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

สตริงรูปแบบเหมาะอย่างยิ่งสำหรับวัตถุประสงค์ในการแปล ฯลฯ แต่ในกรณีเช่นการต่อกันนี้จะง่ายกว่าและใช้งานได้ดีเช่นกัน

ด้วย C # 6

การแก้ไขสตริงทำให้หลายสิ่งง่ายขึ้นในการอ่าน C # 6 ในกรณีนี้รหัสที่สองของคุณจะกลายเป็น:

xlsSheet.Write($"C{rowIndex}", null, title);

ซึ่งน่าจะเป็นตัวเลือกที่ดีที่สุด IMO



ฉันรู้ว่าฉันรู้ว่า. มันถูกสร้างขึ้นด้วยความตลกขบขัน (เคยอ่านลิงค์ btw มาก่อนซึ่งน่าอ่านมาก)
nawfal

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

3
@ mbomb007: ตอนนี้ที่codeblog.jonskeet.uk/2008/10/08/…
Jon Skeet

4
ตอนนี้ C # 6 พร้อมใช้งานคุณสามารถใช้ไวยากรณ์การแก้ไขสตริงใหม่สำหรับสิ่งที่ฉันคิดว่าอ่านง่ายยิ่งขึ้น:xlsSheet.Write($"C{rowIndex}", null, title);
HotN

158

ค่ากำหนดเริ่มต้นของฉัน (มาจากพื้นหลัง C ++) สำหรับ String.Format ฉันทิ้งสิ่งนี้ในภายหลังเนื่องจากสาเหตุต่อไปนี้:

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

- การต่อสายอักขระช่วยให้สามารถหาค่าว่างString.Formatไม่ได้ การเขียน " s1 + null + s2" ไม่ได้ทำลายเพียงแค่ถือว่าค่า null เป็น String.Empty สิ่งนี้อาจขึ้นอยู่กับสถานการณ์เฉพาะของคุณ - มีบางกรณีที่คุณต้องการข้อผิดพลาดแทนที่จะเพิกเฉยต่อ FirstName ที่ว่างเปล่า อย่างไรก็ตามแม้ในสถานการณ์นี้ฉันเองก็ชอบตรวจสอบ nulls ด้วยตัวเองและโยนข้อผิดพลาดเฉพาะแทนที่จะเป็น ArgumentNullException มาตรฐานที่ฉันได้รับจาก String.Format

  • การต่อสตริงทำได้ดีกว่า บางส่วนของโพสต์ด้านบนได้กล่าวถึงสิ่งนี้แล้ว (โดยไม่ได้อธิบายว่าทำไมซึ่งกำหนดให้ฉันเขียนโพสต์นี้ :)

Idea คือคอมไพเลอร์. NET ฉลาดพอที่จะแปลงโค้ดชิ้นนี้:

public static string Test(string s1, int i2, int i3, int i4, 
        string s5, string s6, float f7, float f8)
{
    return s1 + " " + i2 + i3 + i4 + " ddd " + s5 + s6 + f7 + f8;
}

สำหรับสิ่งนี้:

public static string Test(string s1, int i2, int i3, int i4,
            string s5, string s6, float f7, float f8)
{
    return string.Concat(new object[] { s1, " ", i2, i3, i4, 
                    " ddd ", s5, s6, f7, f8 });
}

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

เหตุผลString.Concatเร็วกว่าไหม เราทุกคนสามารถดูได้ว่าString.Formatกำลังทำอะไรอยู่ - คุณจะประหลาดใจกับจำนวนรหัสที่ต้องใช้ในการประมวลผลสตริงรูปแบบ นอกจากนี้ (ฉันเห็นความคิดเห็นเกี่ยวกับการใช้หน่วยความจำ) String.Formatใช้ StringBuilder ภายใน วิธีการมีดังนี้

StringBuilder builder = new StringBuilder(format.Length + (args.Length * 8));

ดังนั้นสำหรับทุกอาร์กิวเมนต์ที่ผ่านไปจะสงวนไว้ 8 อักขระ ถ้าอาร์กิวเมนต์เป็นค่าตัวเลขเดียวก็แย่เหมือนกันเรามีพื้นที่ที่สูญเปล่า หากอาร์กิวเมนต์เป็นออบเจ็กต์ที่กำหนดเองที่ส่งคืนข้อความยาวบางส่วนToString()อาจจำเป็นต้องมีการจัดสรรใหม่ (แน่นอนว่าเป็นกรณีที่เลวร้ายที่สุด)

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

เหตุผลเดียวที่ฉันเลือกใช้ String รูปแบบคือเมื่อเกี่ยวข้องกับการแปล การใส่สตริงรูปแบบในทรัพยากรช่วยให้คุณสามารถรองรับภาษาต่างๆได้โดยไม่ต้องยุ่งกับโค้ด (ลองนึกถึงสถานการณ์ที่ค่าที่จัดรูปแบบเปลี่ยนลำดับขึ้นอยู่กับภาษากล่าวคือ "หลังจาก {0} ชั่วโมงและ {1} นาที" ในภาษาญี่ปุ่นอาจดูแตกต่างกันมาก: )


สรุปโพสต์แรก (และค่อนข้างยาว) ของฉัน:

  • วิธีที่ดีที่สุด (ในแง่ของประสิทธิภาพเทียบกับความสามารถในการบำรุงรักษา / ความสามารถในการอ่าน) สำหรับฉันคือการใช้การต่อสายอักขระโดยไม่ต้องToString()เรียกใด ๆ
  • ถ้าคุณหลังการแสดงให้ToString()โทรหาตัวเองเพื่อหลีกเลี่ยงการชกมวย (ฉันค่อนข้างเอนเอียงไปทางอ่านง่าย) - เหมือนกับตัวเลือกแรกในคำถามของคุณ
  • หากคุณกำลังแสดงสตริงที่แปลเป็นภาษาท้องถิ่นให้กับผู้ใช้ (ไม่ใช่ในกรณีนี้) String.Format()มีขอบ

5
1) string.Format"ปลอดภัย" เมื่อใช้ ReSharper; นั่นคือปลอดภัยพอ ๆ กับรหัสอื่น ๆ ที่สามารถใช้ได้ [ไม่ถูกต้อง] 2) string.Format ไม่อนุญาตให้ "ปลอดภัย" null: string.Format("A{0}B", (string)null)ผลลัพธ์เป็น "AB" 3) ฉันไม่ค่อยสนใจเกี่ยวกับประสิทธิภาพระดับนี้ (และในตอนท้ายมันเป็นวันที่หายากเมื่อฉันดึงออกมาStringBuilder) ...

เห็นด้วยกับ 2) ฉันจะแก้ไขโพสต์ ไม่สามารถตรวจสอบได้ว่าสิ่งนี้ปลอดภัยใน 1.1 หรือไม่ แต่เฟรมเวิร์กล่าสุดนั้นปลอดภัยแน่นอน
แดนค.

string.Concat ยังคงใช้อยู่หรือไม่หากหนึ่งในตัวถูกดำเนินการเป็นการเรียกใช้เมธอดด้วยค่าส่งคืนแทนที่จะเป็นพารามิเตอร์หรือตัวแปร?
Richard Collette

2
@RichardCollette ใช่ String.Concat ถูกใช้แม้กระทั่งของคุณต่อค่าส่งคืนของการเรียกวิธีการเช่นstring s = "This " + MyMethod(arg) + " is a test";รวบรวมไปยังการString.Concat()โทรในโหมดรีลีส
แดนค.

คำตอบที่ยอดเยี่ยม; เขียนและอธิบายได้ดีมาก
Frank V

6

ฉันคิดว่าตัวเลือกแรกนั้นอ่านได้ง่ายกว่าและนั่นควรเป็นข้อกังวลหลักของคุณ

xlsSheet.Write("C" + rowIndex.ToString(), null, title);

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

ไม่ว่าจะด้วยวิธีใดให้เขียนเพื่อให้อ่านง่ายก่อนจากนั้นใช้ตัวสร้างโปรไฟล์ประสิทธิภาพเพื่อระบุฮอตสปอตของคุณหากคุณคิดว่าคุณมีปัญหาด้านประสิทธิภาพจริงๆ



5

สำหรับกรณีง่ายๆที่เป็นการเชื่อมต่อกันเพียงครั้งเดียวฉันรู้สึกว่ามันไม่คุ้มกับความซับซ้อนstring.Format(และฉันยังไม่ได้ทดสอบ แต่ฉันสงสัยว่าสำหรับกรณีง่ายๆเช่นนี้string.Format อาจช้ากว่าเล็กน้อยสิ่งที่มีการแยกวิเคราะห์สตริงรูปแบบ และทั้งหมด). เช่นเดียวกับ Jon Skeet ฉันไม่ต้องการเรียกอย่างชัดเจน.ToString()เนื่องจากจะต้องทำโดยปริยายจากการstring.Concat(string, object)โอเวอร์โหลดและฉันคิดว่าโค้ดนั้นดูสะอาดและอ่านง่ายขึ้นหากไม่มีมัน

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

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

Console.WriteLine(
    "Dear {0} {1},\n\n" +

    "Our records indicate that your {2}, \"{3}\", is due for {4} {5} shots.\n" +
    "Please call our office at 1-900-382-5633 to make an appointment.\n\n" +

    "Thank you,\n" +
    "Eastern Veterinary",

    /*0*/client.Title,
    /*1*/client.LastName,
    /*2*/client.Pet.Animal,
    /*3*/client.Pet.Name,
    /*4*/client.Pet.Gender == Gender.Male ? "his" : "her",
    /*5*/client.Pet.Schedule[0]
);

ปรับปรุง

สำหรับฉันแล้วว่าตัวอย่างที่ฉันให้มานั้นค่อนข้างสับสนเพราะดูเหมือนว่าฉันใช้ทั้งการเรียงต่อกันและstring.Formatที่นี่ ใช่เหตุผลและศัพท์นั่นคือสิ่งที่ฉันทำ แต่การเรียงต่อกันทั้งหมดจะถูกปรับให้เหมาะสมโดยคอมไพเลอร์1เนื่องจากเป็นตัวอักษรสตริงทั้งหมด ดังนั้นในรันไทม์จะมีสตริงเดียว ดังนั้นผมคิดว่าผมควรจะพูดว่าฉันชอบที่จะหลีกเลี่ยงการ concatenations จำนวนมากในเวลาทำงาน

แน่นอนว่าหัวข้อนี้ส่วนใหญ่ล้าสมัยแล้วเว้นแต่คุณจะยังคงใช้ C # 5 หรือเก่ากว่า ตอนนี้เรามีสตริงการแก้ไขซึ่งสำหรับความสามารถในการอ่านนั้นเหนือกว่าstring.Formatในเกือบทุกกรณี ทุกวันนี้เว้นเสียแต่ว่าฉันจะเชื่อมค่าโดยตรงกับจุดเริ่มต้นหรือจุดสิ้นสุดของตัวอักษรสตริงฉันมักจะใช้การแก้ไขสตริง วันนี้ฉันจะเขียนตัวอย่างก่อนหน้านี้ดังนี้:

Console.WriteLine(
    $"Dear {client.Title} {client.LastName},\n\n" +

    $"Our records indicate that your {client.Pet.Animal}, \"{client.Pet.Name}\", " +
    $"is due for {(client.Pet.Gender == Gender.Male ? "his" : "her")} " +
    $"{client.Pet.Schedule[0]} shots.\n" +
    "Please call our office at 1-900-382-5633 to make an appointment.\n\n" +

    "Thank you,\n" +
    "Eastern Veterinary"
);

คุณสูญเสียการเชื่อมต่อเวลาคอมไพล์ด้วยวิธีนี้ สตริงที่ถูกแก้ไขแต่ละสตริงจะกลายเป็นการเรียกstring.Formatโดยคอมไพลเลอร์และผลลัพธ์จะถูกเชื่อมต่อกันในขณะรันไทม์ นั่นหมายความว่านี่คือการเสียสละประสิทธิภาพรันไทม์เพื่อให้อ่านง่าย เวลาส่วนใหญ่เป็นการเสียสละที่คุ้มค่าเพราะบทลงโทษในเวลาวิ่งมีความสำคัญเล็กน้อย อย่างไรก็ตามในโค้ดที่สำคัญด้านประสิทธิภาพคุณอาจต้องกำหนดโปรไฟล์โซลูชันต่างๆ


1 คุณสามารถดูสิ่งนี้ได้ในข้อกำหนด C # :

... อนุญาตให้สร้างโครงสร้างต่อไปนี้ในนิพจน์คงที่:

...

  • ตัวดำเนินการไบนารี + ... ที่กำหนดไว้ล่วงหน้า ...

คุณยังสามารถตรวจสอบได้ด้วยรหัสเล็กน้อย:

const string s =
    "This compiles successfully, " +
    "and you can see that it will " +
    "all be one string (named `s`) " +
    "at run time";

1
fyi คุณสามารถใช้ @ "... multi line string" แทนการเรียงต่อกันทั้งหมด
Aaron Palmer

ใช่ แต่คุณต้องจัดสตริงของคุณให้ชิดซ้าย @ strings รวมบรรทัดใหม่ทั้งหมดและอักขระแท็บระหว่างเครื่องหมายคำพูด
P Daddy

ฉันรู้ว่านี่เก่า แต่เป็นกรณีที่ฉันบอกว่าใส่สตริงรูปแบบในไฟล์ resx
Andy

2
ว้าวทุกคนมุ่งความสนใจไปที่ตัวอักษรสตริงแทนที่จะเป็นหัวใจของเรื่องนี้
P Daddy

heheh - ฉันเพิ่งสังเกตเห็นการต่อสตริงภายในของคุณString.Format()
Kristopher

3

หากสตริงของคุณซับซ้อนขึ้นโดยมีการต่อตัวแปรหลายตัวฉันจะเลือก string.Format () แต่สำหรับขนาดของสตริงและจำนวนของตัวแปรที่ถูกตัดแบ่งในกรณีของคุณผมไปกับรุ่นแรกของคุณก็มากขึ้นสปาร์ตัน


3

ฉันได้ดู String.Format (โดยใช้ตัวสะท้อนแสง) และมันสร้าง StringBuilder ขึ้นมาจากนั้นเรียก AppendFormat ดังนั้นจึงเร็วกว่า concat สำหรับการกวนหลาย ๆ เร็วที่สุด (ฉันเชื่อว่า) จะสร้าง StringBuilder และทำการเรียกเพื่อผนวกด้วยตนเอง แน่นอนว่าจำนวน "หลาย" นั้นขึ้นอยู่กับการคาดเดา ฉันจะใช้ + (จริงๆแล้ว & เพราะฉันเป็นโปรแกรมเมอร์ VB เป็นส่วนใหญ่) สำหรับบางสิ่งที่เรียบง่ายดังตัวอย่างของคุณ เมื่อมันซับซ้อนขึ้นฉันจึงใช้ String.Format หากมีตัวแปรจำนวนมากฉันจะไปหา StringBuilder และ Append เช่นเรามีโค้ดที่สร้างโค้ดที่นั่นฉันใช้โค้ดจริงหนึ่งบรรทัดเพื่อส่งออกโค้ดที่สร้างขึ้นหนึ่งบรรทัด

ดูเหมือนจะมีการคาดเดาเกี่ยวกับจำนวนสตริงที่สร้างขึ้นสำหรับแต่ละการดำเนินการเหล่านี้ดังนั้นลองมาดูตัวอย่างง่ายๆ

"C" + rowIndex.ToString();

"C" เป็นสตริงอยู่แล้ว
rowIndex ToString () สร้างสตริงอื่น (@manohard - จะไม่มีการชกมวยของ rowIndex)
จากนั้นเราจะได้สตริงสุดท้าย
ถ้าเราใช้ตัวอย่างของ

String.Format("C(0)",rowIndex);

จากนั้นเราจะมี "C {0}" เป็นสตริง
rowIndex ที่จะถูกส่งผ่านไปยังฟังก์ชัน
มีการสร้าง stringbuilder ใหม่
AppendFormat ถูกเรียกบนตัวสร้างสตริง - ฉันไม่รู้รายละเอียดของฟังก์ชัน AppendFormat แต่สมมติว่าเป็น มีประสิทธิภาพเป็นพิเศษก็ยังคงต้องแปลง rowIndex แบบบรรจุกล่องเป็นสตริง
จากนั้นแปลง stringbuilder เป็นสตริงใหม่
ฉันรู้ว่า StringBuilders พยายามป้องกันไม่ให้เกิดการคัดลอกหน่วยความจำแบบไม่มีจุดหมาย แต่ String.Format ยังคงจบลงด้วยค่าใช้จ่ายพิเศษเมื่อเทียบกับการต่อแบบธรรมดา

ถ้าตอนนี้เราจะยกตัวอย่างกับสตริงเพิ่มเติม

"a" + rowIndex.ToString() + "b" + colIndex.ToString() + "c" + zIndex.ToString();

เรามี 6 สายที่จะเริ่มต้นซึ่งจะเหมือนกันสำหรับทุกกรณี
การใช้การเรียงต่อกันเรายังมี 4 สตริงกลางรวมถึงผลลัพธ์สุดท้าย เป็นผลลัพธ์ระดับกลางที่ถูกกำจัดโดยใช้ String, Format (หรือ StringBuilder)
โปรดจำไว้ว่าในการสร้างสตริงกลางแต่ละสตริงจะต้องคัดลอกสตริงก่อนหน้านี้ไปยังตำแหน่งหน่วยความจำใหม่ไม่ใช่แค่การจัดสรรหน่วยความจำที่อาจช้า


4
nitpick ใน "a" + ... + "b" + ... + "c" + ... คุณจะไม่มีสตริงกลาง 4 สาย คอมไพเลอร์จะสร้างการเรียกใช้เมธอดแบบคงที่ String.Concat (params string [] values) และทั้งหมดจะเชื่อมต่อพร้อมกัน ฉันยังคงชอบสตริงแม้ว่ารูปแบบเพื่อประโยชน์ในการอ่าน
พ่อพ่อ

2

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

สำหรับการต่อกันภายในลูปหรือในสตริงขนาดใหญ่คุณควรพยายามใช้คลาส StringBuilder เสมอ


2

ตัวอย่างนั้นอาจเป็นเรื่องเล็กน้อยเกินไปที่จะสังเกตเห็นความแตกต่าง ในความเป็นจริงฉันคิดว่าในกรณีส่วนใหญ่คอมไพเลอร์สามารถปรับความแตกต่างได้ทั้งหมด

อย่างไรก็ตามถ้าฉันต้องเดาฉันจะให้string.Format()ความได้เปรียบสำหรับสถานการณ์ที่ซับซ้อนมากขึ้น แต่นั่นเป็นความรู้สึกที่น่าเบื่อกว่านั่นคือน่าจะทำงานได้ดีกว่าโดยใช้บัฟเฟอร์แทนที่จะสร้างสตริงที่ไม่เปลี่ยนรูปหลาย ๆ สายและไม่ได้ขึ้นอยู่กับข้อมูลจริงใด ๆ


1

ฉันเห็นด้วยกับหลายประเด็นข้างต้นอีกประเด็นหนึ่งที่ฉันเชื่อว่าควรกล่าวถึงคือการบำรุงรักษาโค้ด string.Format ช่วยให้เปลี่ยนรหัสได้ง่ายขึ้น

เช่นฉันมีข้อความ "The user is not authorized for location " + locationหรือ "The User is not authorized for location {0}"

หากฉันต้องการเปลี่ยนข้อความเป็นพูดว่า: location + " does not allow this User Access"หรือ "{0} does not allow this User Access"

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

หากใช้ในหลายสถานที่สามารถประหยัดเวลาได้


1

ฉันรู้สึกว่า string.format เร็วกว่าดูเหมือนว่าจะช้าลง 3 เท่าในการทดสอบนี้

string concat = "";
        System.Diagnostics.Stopwatch sw1 = new System.Diagnostics.Stopwatch    ();
        sw1.Start();
        for (int i = 0; i < 10000000; i++)
        {
            concat = string.Format("{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}","1", "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , i);
        }
        sw1.Stop();
        Response.Write("format: "  + sw1.ElapsedMilliseconds.ToString());
        System.Diagnostics.Stopwatch sw2 = new System.Diagnostics.Stopwatch();
        sw2.Start();
        for (int i = 0; i < 10000000; i++)
        {
            concat = "1" + "2" + "3" + "4" + "5" + "6" + "7" + "8" + "9" + "10" + i;
        }
        sw2.Stop();

string.format ใช้เวลา 4.6 วินาทีและเมื่อใช้ '+' จะใช้เวลา 1.6 วินาที


7
คอมไพเลอร์รับรู้"1" + "2" + "3" + "4" + "5" + "6" + "7" + "8" + "9" + "10"ว่าเป็นสตริงตามตัวอักษรหนึ่งบรรทัดดังนั้นบรรทัดจะกลายเป็น"12345678910" + iสิ่งที่เร็วกว่าก่อนหน้านี้อย่างมีประสิทธิภาพstring.Format(...)
wertzui

0

string.Format น่าจะเป็นทางเลือกที่ดีกว่าเมื่อเก็บเทมเพลตรูปแบบ ("C {0}") ไว้ในไฟล์กำหนดค่า (เช่น Web.config / App.config)


0

ฉันทำโปรไฟล์วิธีการสตริงต่างๆรวมถึง string.Format, StringBuilder และการต่อสายอักขระ การต่อสายอักขระมักจะมีประสิทธิภาพดีกว่าวิธีอื่น ๆ ในการสร้างสตริง ดังนั้นหากประสิทธิภาพเป็นสิ่งสำคัญก็จะดีกว่า อย่างไรก็ตามหากประสิทธิภาพไม่สำคัญฉันเองก็พบว่าสตริงรูปแบบจะง่ายต่อการติดตามในโค้ด (แต่นั่นเป็นเหตุผลส่วนตัว) อย่างไรก็ตาม StringBuilder น่าจะมีประสิทธิภาพมากที่สุดเมื่อเทียบกับการใช้หน่วยความจำ



-1

การต่อสายอักขระใช้หน่วยความจำมากกว่าเมื่อเทียบกับ String.Format วิธีที่ดีที่สุดในการต่อสตริงคือการใช้ String.Format หรือ System.Text.StringBuilder Object

ลองพิจารณากรณีแรก: "C" + rowIndex ToString () สมมติว่า rowIndex เป็นประเภทค่าดังนั้น ToString () จึงต้อง Box เพื่อแปลงค่าเป็น String จากนั้น CLR จะสร้างหน่วยความจำสำหรับสตริงใหม่โดยมีทั้งสองค่ารวมอยู่ด้วย

โดยที่เป็น string.Format คาดหวังพารามิเตอร์ object และรับ rowIndex เป็น object และแปลงเป็น string ภายใน offcourse จะมี Boxing แต่เป็นแบบภายในและจะไม่ใช้หน่วยความจำมากเท่ากับในกรณีแรก

สำหรับสายสั้นมันคงไม่สำคัญเท่าไหร่หรอก ...

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