วิธีที่มีประสิทธิภาพมากที่สุดในการต่อสตริง?


286

วิธีที่มีประสิทธิภาพมากที่สุดในการเชื่อมสตริงคืออะไร


9
ฉันต้องการวางคำเตือนที่โดดเด่นที่นี่ว่าคำตอบที่ยอมรับนั้นไม่สมบูรณ์อย่างมากเพราะไม่ได้พูดถึงกรณีที่เกี่ยวข้องทั้งหมด
usr

@usr แท้จริง ... ดูรายละเอียดเพิ่มเติมเกี่ยวกับStringBuilderกรณีการใช้งานที่สามารถพบได้ที่นี่
Tamir Vered

รายการโปรดใหม่ของฉันในชื่อ C # 6 คือ $ "ข้อความคงที่ที่นี่ {foo} และ {bar}" ... มันเหมือนกับString.Formatเตียรอยด์ ซึ่งประสิทธิภาพที่ชาญฉลาดนั้นจะช้ากว่านิดหน่อยที่หนึ่ง liners +และString.Concatแต่ดีกว่านั้นแม้ว่าจะช้ากว่าStringBuilderที่หลายสาย พูดจริงแล้วความแตกต่างด้านประสิทธิภาพนั้นถ้าฉันต้องเลือกวิธีเดียวที่จะต่อกันฉันจะเลือกการแก้ไขสตริงโดยใช้$... หากสองวิธีแล้วเพิ่มStringBuilderไปยังกล่องเครื่องมือของฉัน ด้วยสองวิธีที่คุณตั้งไว้
u8it

String.Joinคำตอบดังต่อไปนี้ไม่ได้ทำ+ความยุติธรรมและความเป็นจริงที่พูดเป็นวิธีที่ดีที่จะสตริง concatenate แต่มันเป็นผลการดำเนินงานได้อย่างรวดเร็วน่าแปลกใจที่ชาญฉลาด คำตอบว่าทำไมถึงน่าสนใจ String.ConcatและString.Joinสามารถกระทำได้ทั้งในอาร์เรย์ แต่String.Joinจริงๆแล้วเร็วกว่า เห็นได้ชัดว่าString.Joinมันค่อนข้างซับซ้อนและปรับให้เหมาะสมมากกว่าString.Concatส่วนหนึ่งเป็นเพราะมันทำงานคล้ายกับStringBuilderที่มันคำนวณความยาวของสตริงก่อนแล้วจึงสร้างสตริงที่ได้รับประโยชน์จากความรู้นี้โดยใช้ UnSafeCharBuffer
u8it

ตกลงดังนั้นมันเร็ว แต่String.Joinยังต้องมีการสร้างอาร์เรย์ซึ่งดูเหมือนว่าทรัพยากรไม่มีประสิทธิภาพใช่หรือไม่ ... เปิดออก+และString.Concatสร้างอาร์เรย์สำหรับองค์ประกอบของพวกเขาอยู่ดี ดังนั้นการสร้างตนเองอาร์เรย์และการให้อาหารมันString.Joinค่อนข้างเร็วขึ้น ... แต่StringBuilderยังคงมีประสิทธิภาพดีกว่าString.Joinในทุกวิธีการปฏิบัติในขณะที่ยัง$เป็นเพียงช้าลงเล็กน้อยและเร็วขึ้นมากในสายยาว ... ไม่ต้องพูดถึงว่ามันเป็นที่น่าอึดอัดใจและน่าเกลียดที่จะใช้String.Joinถ้าคุณมี เพื่อสร้างอาร์เรย์สำหรับมันในจุดที่
u8it

คำตอบ:


155

StringBuilder.Append()เป็นวิธีการที่ดีกว่าการใช้+ประกอบการ แต่ฉันได้พบว่าเมื่อมีการดำเนิน 1,000 concatenations หรือน้อยกว่าแม้จะมีประสิทธิภาพมากกว่าString.Join()StringBuilder

StringBuilder sb = new StringBuilder();
sb.Append(someString);

ปัญหาเดียวString.Joinคือคุณต้องเชื่อมสตริงด้วยตัวคั่นทั่วไป

แก้ไข:ตามที่@ryanversawชี้ให้เห็นคุณสามารถสร้างตัวคั่นstring.Emptyได้

string key = String.Join("_", new String[] 
{ "Customers_Contacts", customerID, database, SessionID });

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

32
สิ่งนี้ไม่เป็นความจริงสำหรับการต่อข้อมูลบรรทัดเดียว สมมติว่าคุณทำ myString = "foo" + var1 + "bar" + var2 + "hello" + var3 + "world" คอมไพเลอร์จะเปลี่ยนมันเป็นการโทรแบบ string.concat โดยอัตโนมัติซึ่งมีประสิทธิภาพเท่ากับที่ได้รับ คำตอบนี้ไม่ถูกต้องมีคำตอบที่ดีกว่าให้เลือกมากมาย
csauve

2
สำหรับการรวมสตริงสตริงเล็กน้อยใช้สิ่งที่เคยอ่านได้มากที่สุด สตริง a = b + c + d; จะเกือบจะเร็วกว่าการทำด้วย StringBuilder แต่โดยทั่วไปแล้วความแตกต่างนั้นไม่เกี่ยวข้อง ใช้ StringBuilder (หรือตัวเลือกอื่น ๆ ที่คุณเลือก) เมื่อเพิ่มไปยังสตริงเดิมซ้ำ ๆ (เช่นการสร้างรายงาน) หรือเมื่อต้องจัดการกับสตริงจำนวนมาก
Swanny

5
ทำไมคุณยังไม่ได้กล่าวถึงstring.Concat?
Venemo

272

Rico Mariani , ปรมาจารย์ด้าน. ประสิทธิภาพ NET, มีบทความเกี่ยวกับเรื่องนี้มาก มันไม่ง่ายอย่างที่ใคร ๆ ก็สงสัย คำแนะนำพื้นฐานคือ:

หากรูปแบบของคุณดูเหมือนว่า:

x = f1(...) + f2(...) + f3(...) + f4(...)

นั่นเป็นหนึ่งในความเชื่อมโยงกันและมันมีชีวิตชีวา แต่ StringBuilder อาจไม่ช่วยได้

หากรูปแบบของคุณดูเหมือนว่า:

if (...) x += f1(...)
if (...) x += f2(...)
if (...) x += f3(...)
if (...) x += f4(...)

จากนั้นคุณอาจต้องการ StringBuilder

บทความอื่นที่ให้การสนับสนุนการอ้างสิทธิ์นี้มาจาก Eric Lippert ซึ่งเขาอธิบายการปรับให้เหมาะสมที่ดำเนินการในการ+ต่อข้อมูลบรรทัดเดียวในรายละเอียด


1
สิ่งที่เกี่ยวกับ String.Format ()?
IronSlug

86

การต่อสตริงมี 6 ชนิด:

  1. การใช้+สัญลักษณ์เครื่องหมายบวก ( )
  2. string.Concat()การใช้
  3. string.Join()การใช้
  4. string.Format()การใช้
  5. string.Append()การใช้
  6. StringBuilderการใช้

ในการทดสอบได้รับการพิสูจน์แล้วว่าstring.Concat()เป็นวิธีที่ดีที่สุดในการเข้าหาถ้าคำนั้นน้อยกว่า 1,000 (โดยประมาณ) และถ้าคำนั้นมีมากกว่า 1,000StringBuilderควรใช้

สำหรับข้อมูลเพิ่มเติมตรวจสอบเว็บไซต์นี้

string.Join () vs string.Concat ()

เมธอด string.Concat ที่นี่เทียบเท่ากับการเรียกเมธอด string.Join ด้วยตัวคั่นว่าง การต่อท้ายสตริงว่างเร็ว แต่การทำเช่นนั้นจะไม่เร็วกว่าดังนั้นเมธอดstring.Concatน่าจะดีกว่าที่นี่


4
ควรอ่านมันได้รับการพิสูจน์แล้ว string.Catcat () หรือ + เป็นวิธีที่ดีที่สุด ใช่ฉันสามารถรับสิ่งนี้จากบทความ แต่มันช่วยฉันด้วยการคลิกเพียงครั้งเดียว ดังนั้น + และ concat รวบรวมเป็นรหัสเดียวกัน
brumScouse

ฉันใช้พื้นฐานนี้เพื่อลองและทำให้วิธีการของฉันมีประสิทธิภาพมากขึ้นโดยที่ฉันเพียงต้องการเชื่อมต่อ 3 สตริงเท่านั้น ฉันพบว่า+เป็นจริง 3 มิลลิวินาทีเร็วกว่าstring.Concat()แต่ผมยังไม่ได้มองเข้าไปในจำนวนของสตริงที่จำเป็นก่อนที่จะoutracesstring.Concat() +
Gnemlock

59

จากChinh Do - StringBuilder ไม่ได้เร็วขึ้นเสมอ :

กฎของ Thumb

  • เมื่อทำการต่อค่าสตริงแบบไดนามิกสามค่าหรือน้อยกว่าให้ใช้การต่อสตริงแบบดั้งเดิม

  • เมื่อเชื่อมโยงมากกว่าสามStringBuilderค่าสตริงแบบไดนามิกการใช้งาน

  • เมื่อสร้างสตริงขนาดใหญ่จากตัวอักษรสตริงหลายตัวให้ใช้@ตัวอักษรสตริงหรือตัวดำเนินการ inline +

ส่วนใหญ่ของเวลาStringBuilderเป็นทางออกที่ดีที่สุดของคุณ แต่มีกรณีตามที่ปรากฏในโพสต์ที่ว่าอย่างน้อยคุณควรคิดเกี่ยวกับแต่ละสถานการณ์


8
afaik @ ปิดการประมวลผลลำดับเอสเคปเท่านั้น msdn.microsoft.com/en-us/library/362314fe.aspxเห็นด้วย
abatishchev

12

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

อย่างไรก็ตามเปอร์โตริโก Mariani (.NET เพิ่มประสิทธิภาพกูรู) ที่สร้างขึ้นแบบทดสอบString.Formatซึ่งเขาระบุในตอนท้ายว่าในกรณีส่วนใหญ่ที่เขาแนะนำ


ฉันแนะนำให้ใช้ string.format ผ่าน string + string มานานหลายปีแล้วกับคนที่ฉันเคยทำงานด้วย ฉันคิดว่าข้อดีการอ่านคือข้อดีเพิ่มเติมนอกเหนือจากประโยชน์ด้านประสิทธิภาพ
Scott Lawrence

1
นี่คือคำตอบที่ถูกต้องจริง คำตอบที่ได้รับการยอมรับในปัจจุบันสำหรับ StringBuilder ไม่ถูกต้องเนื่องจากไม่ได้กล่าวถึงบรรทัดเดียวต่อท้ายซึ่ง string.concat หรือ + เร็วกว่า ความจริงที่รู้จักกันน้อยคือคอมไพเลอร์แปล + ของจริงเป็น string.concat นอกจากนี้สำหรับ loops หรือหลาย concats บรรทัดฉันใช้ตัวสร้างสตริงที่กำหนดเองที่ผนวกเฉพาะเมื่อ. ToString ถูกเรียก - เอาชนะปัญหาบัฟเฟอร์ไม่แน่นอนที่ StringBuilder มี
csauve

2
string รูปแบบไม่ใช่วิธีที่เร็วที่สุดภายใต้สถานการณ์ใด ๆ ฉันไม่รู้วิธีประดิษฐ์กรณีที่เกิดขึ้นล่วงหน้า
usr

@usr - โปรดทราบว่า Rico ไม่ได้กล่าวอย่างชัดเจนว่าเป็นวิธีที่เร็วที่สุดเพียง แต่เป็นคำแนะนำของเขา: "แม้ว่ามันจะเป็นการแสดงที่แย่ที่สุดและเรารู้ล่วงหน้ามากว่าทั้ง CLR Performance Architects ของคุณเห็นด้วยกับ [string.Format] เป็นตัวเลือกเริ่มต้นในกรณีที่ไม่น่าเป็นไปได้สูงที่จะกลายเป็นปัญหาที่สมบูรณ์ปัญหาสามารถแก้ไขได้อย่างง่ายดายด้วยการเปลี่ยนแปลงในท้องถิ่นเพียงเล็กน้อยโดยปกติแล้วคุณเพียงแค่ cashing-in ในการบำรุงรักษาที่ดี "
อดัมวี

@ AdamV คำถามคือเกี่ยวกับวิธีที่เร็วที่สุด ฉันไม่ชอบมันเป็นตัวเลือกเริ่มต้น แต่ไม่ใช่ด้วยเหตุผลที่สมบูรณ์แบบ มันอาจเป็นซุ่มซ่ามซินแท็คซ์ Resharper สามารถแปลงไปมาได้ตามต้องการ
usr

10

นี่เป็นวิธีที่เร็วที่สุดที่ฉันได้พัฒนามานานกว่าทศวรรษสำหรับแอป NLP ขนาดใหญ่ของฉัน ฉันมีรูปแบบIEnumerable<T>และประเภทอินพุตอื่น ๆ ที่มีและไม่มีตัวคั่นประเภทที่แตกต่างกัน ( Char, String) แต่ที่นี่ฉันแสดงกรณีง่าย ๆ ของการ เชื่อมสตริงทั้งหมดในอาร์เรย์เป็นสตริงเดียวโดยไม่มีตัวคั่น รุ่นล่าสุดที่นี่ได้รับการพัฒนาและทดสอบหน่วยบนC # 7และ. NET 4.74.7

มีสองปุ่มเพื่อประสิทธิภาพที่สูงขึ้น สิ่งแรกคือการคำนวณขนาดทั้งหมดที่ต้องการล่วงหน้า ขั้นตอนนี้ไม่สำคัญเมื่ออินพุตเป็นอาร์เรย์ดังที่แสดงไว้ที่นี่ สำหรับการจัดการIEnumerable<T>แทนมันคุ้มค่าก่อนที่จะรวบรวมสตริงลงในอาร์เรย์ชั่วคราวสำหรับการคำนวณทั้งหมด (ต้องใช้อาร์เรย์เพื่อหลีกเลี่ยงการโทรToString()มากกว่าหนึ่งครั้งต่อองค์ประกอบตั้งแต่ในทางเทคนิคให้ความเป็นไปได้ของผลข้างเคียงทำให้เปลี่ยนความหมายที่คาดไว้ ของการดำเนินการ 'เข้าร่วมสตริง')

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

... ทราบว่านี่เป็นวิธีการแก้ปัญหาเป็นกลุ่มเรียงต่อกันเฉพาะในหน้านี้ซึ่งทั้งหลีกเลี่ยงรอบพิเศษของการจัดสรรและการคัดลอกโดยStringคอนสตรัค

รหัสสมบูรณ์:

/// <summary>
/// Concatenate the strings in 'rg', none of which may be null, into a single String.
/// </summary>
public static unsafe String StringJoin(this String[] rg)
{
    int i;
    if (rg == null || (i = rg.Length) == 0)
        return String.Empty;

    if (i == 1)
        return rg[0];

    String s, t;
    int cch = 0;
    do
        cch += rg[--i].Length;
    while (i > 0);
    if (cch == 0)
        return String.Empty;

    i = rg.Length;
    fixed (Char* _p = (s = new String(default(Char), cch)))
    {
        Char* pDst = _p + cch;
        do
            if ((t = rg[--i]).Length > 0)
                fixed (Char* pSrc = t)
                    memcpy(pDst -= t.Length, pSrc, (UIntPtr)(t.Length << 1));
        while (pDst > _p);
    }
    return s;
}

[DllImport("MSVCR120_CLR0400", CallingConvention = CallingConvention.Cdecl)]
static extern unsafe void* memcpy(void* dest, void* src, UIntPtr cb);

ฉันควรพูดถึงว่ารหัสนี้มีการปรับเปลี่ยนเล็กน้อยจากสิ่งที่ฉันใช้ตัวเอง ในต้นฉบับฉันเรียกคำสั่งcpblk ILจากC #เพื่อทำการคัดลอกจริง เพื่อความง่ายและพกพาในรหัสที่นี่ฉันแทนที่ด้วย P / Invoke memcpyแทนตามที่คุณเห็น เพื่อประสิทธิภาพสูงสุดใน x64 ( แต่อาจไม่ใช่ x86 ) คุณอาจต้องการใช้วิธีcpblkแทน


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

1
@Servy ขอบคุณสำหรับความคิดเห็น; แน่นอนString.Joinได้อย่างมีประสิทธิภาพ ตามที่ฉันได้กล่าวไว้ในบทนำรหัสที่นี่เป็นเพียงภาพประกอบที่ง่ายที่สุดของกลุ่มฟังก์ชันที่ฉันใช้สำหรับสถานการณ์ที่String.Joinไม่สามารถจัดการได้ (เช่นการปรับให้เหมาะสมสำหรับCharตัวคั่น) หรือไม่ได้จัดการใน. NET รุ่นก่อนหน้า ฉันคิดว่าฉันไม่ควรเลือกสิ่งนี้เพื่อเป็นตัวอย่างที่ง่ายที่สุดเนื่องจากเป็นกรณีที่String.Joinจัดการได้ดีอยู่แล้วถึงแม้ว่าจะมี "ความไม่มีประสิทธิภาพ" ซึ่งเป็นไปไม่ได้อย่างมากในการประมวลผลตัวคั่นที่ไม่มีความหมาย ได้แก่ String.Empty.
Glenn Slayden

แน่นอนว่าในกรณีที่คุณไม่ได้มีตัวคั่นแล้วคุณควรจะเรียกConcatซึ่งยังไม่ถูกต้อง คุณไม่จำเป็นต้องเขียนโค้ดด้วยตัวเอง
Servy

7
@Servy ฉันได้เปรียบเทียบประสิทธิภาพของString.Joinรหัสของฉันกับชุดทดสอบนี้ สำหรับการดำเนินงาน 10 ล้านเรียงต่อกันแบบสุ่มของได้ถึง 100 คำสตริงขนาดแต่ละรหัสที่ปรากฏข้างต้นเป็นอย่างต่อเนื่อง 34% เร็วกว่าString.Joinบนx64ปล่อยสร้างด้วย.NET 4.7 เนื่องจาก OP ขอวิธี "มีประสิทธิภาพมากที่สุด" อย่างชัดเจนผลลัพธ์จึงชี้ให้เห็นว่าคำตอบของฉันถูกนำไปใช้ หากสิ่งนี้ตอบข้อกังวลของคุณได้ฉันขอเชิญคุณให้พิจารณาทบทวน downvote ของคุณอีกครั้ง
Glenn Slayden

1
ฉันเพิ่งเปรียบเทียบกับ x64 เต็ม CLR 4.7.1 และพบว่ามันเร็วกว่าสตริงถึงสองเท่าเข้าร่วมกับการจัดสรรหน่วยความจำลดลงประมาณ 25% ( i.imgur.com/SxIpEmL.png ) เมื่อใช้ cpblk หรือgithub.com/ JonHanna / Mnemosyne
quentin-starin

6

จากบทความ MSDN นี้ :

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

ดังนั้นถ้าคุณเชื่อถือ MSDN ให้ไปกับ StringBuilder ถ้าคุณต้องทำการดำเนินการสตริงมากกว่า 10 รายการ / การต่อข้อมูล - มิฉะนั้นสตริงแบบง่าย ๆ ที่เชื่อมต่อด้วย '+' นั้นใช้ได้


5

สิ่งสำคัญคือต้องชี้ให้เห็นว่าคุณควรใช้+โอเปอเรเตอร์ถ้าคุณต่อสตริงตัวอักษรเข้าด้วยกัน

เมื่อคุณต่อสตริงตัวอักษรหรือค่าคงที่สตริงเข้าด้วยกันโดยใช้ตัวดำเนินการ + คอมไพเลอร์จะสร้างสตริงเดียว ไม่มีการต่อข้อมูลรันไทม์เกิดขึ้น

วิธีการ: เชื่อมหลายสายเข้าด้วยกัน (คู่มือการเขียนโปรแกรม C #)


5

การเพิ่มคำตอบอื่น ๆ โปรดทราบว่าStringBuilder สามารถบอกจำนวนเงินเริ่มต้นของหน่วยความจำที่จะจัดสรร

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

หากความจุเป็นศูนย์จะใช้ความจุเริ่มต้นเฉพาะการใช้งาน

ผนวกท้ายซ้ำกับ StringBuilder ที่ไม่ได้รับการจัดสรรล่วงหน้าอาจส่งผลให้เกิดการจัดสรรที่ไม่จำเป็นจำนวนมากเช่นเดียวกับการเชื่อมสตริงปกติซ้ำ ๆ

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

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


4

การติดตามอาจเป็นอีกทางเลือกหนึ่งในการเชื่อมหลายสายเข้าด้วยกัน

String str1 = "sometext";
string str2 = "some other text";

string afterConcate = $"{str1}{str2}";

การแก้ไขสตริง


1
นี่เป็นเรื่องที่น่าประหลาดใจมากเพราะเป็นวิธีการต่อข้อมูลทั่วไป มันเป็นพื้นString.Formatแต่อ่านง่ายขึ้นและง่ายต่อการทำงานกับ การทำเครื่องหมายด้วยม้านั่งมันช้ากว่าเล็กน้อย+และString.Concatในการต่อข้อมูลบรรทัดเดียว แต่ดีกว่าทั้งสองอย่างที่การโทรซ้ำ ๆ ทำให้StringBuilderจำเป็นน้อยลง
u8it

2

มีประสิทธิภาพมากที่สุดคือการใช้ StringBuilder เช่น:

StringBuilder sb = new StringBuilder();
sb.Append("string1");
sb.Append("string2");
...etc...
String strResult = sb.ToString();

@ jonezy: String.Concat เป็นเรื่องปกติถ้าคุณมีสองสิ่งเล็ก ๆ น้อย ๆ แต่ถ้าคุณกำลังต่อข้อมูลเมกะไบต์โปรแกรมของคุณจะมีแนวโน้มว่าจะมีการเก็บข้อมูล


เฮ้ทางออกสำหรับเมกะไบต์ของข้อมูลคืออะไร?
Neel

2

ลองโค้ด 2 ชิ้นนี้แล้วคุณจะพบทางออก

 static void Main(string[] args)
    {
        StringBuilder s = new StringBuilder();
        for (int i = 0; i < 10000000; i++)
        {
            s.Append( i.ToString());
        }
        Console.Write("End");
        Console.Read();
    }

Vs

static void Main(string[] args)
    {
        string s = "";
        for (int i = 0; i < 10000000; i++)
        {
            s += i.ToString();
        }
        Console.Write("End");
        Console.Read();
    }

คุณจะพบว่ารหัสที่ 1 จะจบลงอย่างรวดเร็วและหน่วยความจำจะอยู่ในระดับที่ดี

รหัสที่สองอาจจะเป็นหน่วยความจำก็โอเค แต่มันจะใช้เวลานาน ... ดังนั้นหากคุณมีแอปพลิเคชั่นสำหรับผู้ใช้จำนวนมากและคุณต้องการความเร็วให้ใช้อันดับที่ 1 หากคุณมีแอพสำหรับผู้ใช้ระยะสั้นหนึ่งแอพคุณอาจใช้ทั้งสองอย่างหรืออย่างที่สองจะเป็น "ธรรมชาติ" มากกว่าสำหรับนักพัฒนา

ไชโย


1

สำหรับสองสายคุณไม่ต้องการใช้ StringBuilder มีขีด จำกัด ข้างต้นบางส่วนซึ่งค่าโสหุ้ย StringBuilder น้อยกว่าค่าใช้จ่ายในการจัดสรรหลายสาย

ดังนั้นสำหรับมากกว่าที่ 2-3 สตริงใช้รหัส DannySmurf ของ มิฉะนั้นเพียงใช้ตัวดำเนินการ +


1

System.String ไม่เปลี่ยนรูป เมื่อเราแก้ไขค่าของตัวแปรสตริงหน่วยความจำใหม่จะถูกจัดสรรเป็นค่าใหม่และการจัดสรรหน่วยความจำก่อนหน้า System.StringBuilder ถูกออกแบบมาให้มีแนวคิดของสตริงที่ไม่แน่นอนซึ่งสามารถดำเนินการได้หลากหลายโดยไม่ต้องจัดสรรตำแหน่งหน่วยความจำแยกต่างหากสำหรับสตริงที่แก้ไข


1

ทางออกอื่น:

ในลูปให้ใช้รายการแทนสตริง

List<string> lst= new List<string>();

for(int i=0; i<100000; i++){
    ...........
    lst.Add(...);
}
return String.Join("", lst.ToArray());;

มันเร็วมาก


1

มันขึ้นอยู่กับรูปแบบการใช้งานของคุณ เกณฑ์มาตรฐานโดยละเอียดระหว่าง stringJoin, string, Concat และ string สามารถพบได้ที่นี่: String.Format ไม่เหมาะสำหรับการบันทึกแบบเร่งรัด

(นี่เป็นคำตอบเดียวกับที่ฉันให้กับคำถามนี้ )


0

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

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