โดยทั่วไปจะใช้วิธีไหนดีที่สุด - StringComparison.OrdinalIgnoreCase หรือ StringComparison.InvariantCultureIgnoreCase?


162

ฉันมีรหัสเช่นนี้:

If key.Equals("search", StringComparison.OrdinalIgnoreCase) Then
    DoSomething()
End If

ฉันไม่สนใจเรื่องนี้ ฉันควรใช้OrdinalIgnoreCase, InvariantCultureIgnoreCaseหรือCurrentCultureIgnoreCase?


2
ตรวจสอบนี้มันมีประโยชน์จริงๆสำหรับหัวข้อนี้ ข้อเสนอแนะของฉันที่จะใช้ ordianlignorecase สำหรับการเปรียบเทียบ blogs.msdn.com/b/noahc/archive/2007/06/29/…
UmaMaheswaran

พิจารณาคำตอบที่ได้รับการโหวตอย่างสูงจากการเปรียบเทียบสตริงที่
Michael Freidgeim

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

คำตอบ:


180

เอกสาร. Net รุ่นใหม่กว่านี้มีตารางที่จะช่วยคุณตัดสินใจว่าจะใช้สิ่งใดดีที่สุดในสถานการณ์ของคุณ

จาก " คำแนะนำใหม่สำหรับการใช้สตริงใน Microsoft .NET 2.0 " ของ MSDN

สรุป: ก่อนหน้านี้เจ้าของรหัสที่ใช้InvariantCultureสำหรับการเปรียบเทียบสตริงการจัดเรียงและการเรียงลำดับควรพิจารณาอย่างยิ่งว่าจะใช้ชุดStringโอเวอร์โหลดใหม่ใน Microsoft .NET 2.0 โดยเฉพาะอย่างยิ่งข้อมูลที่ออกแบบมาเพื่อไม่เชื่อเรื่องวัฒนธรรมและไม่เกี่ยวข้องกับภาษาควรเริ่มระบุ overloads โดยใช้ทั้งStringComparison.OrdinalหรือStringComparison.OrdinalIgnoreCaseสมาชิกของการStringComparisonแจงนับใหม่ สิ่งเหล่านี้บังคับใช้การเปรียบเทียบแบบไบต์ต่อไบต์คล้ายกับstrcmpที่ไม่เพียง แต่หลีกเลี่ยงข้อบกพร่องจากการตีความภาษาของสตริงสัญลักษณ์เป็นหลัก แต่ให้ประสิทธิภาพที่ดีขึ้น


126
เพื่อให้ตัวอย่างที่พวกเขาแตกต่างกันให้พิจารณาสองสตริงและ"Straße" "STRASSE"เมื่อใช้ผลตอบแทนในขณะที่กล่าวว่าพวกเขากำลังเท่ากัน OrdinalIgnoreCaseEqualsfalseInvariantCultureIgnoreCase
Jeppe Stig Nielsen

2
ลิงก์ที่อัปเดต: docs.microsoft.com/en-us/dotnet/standard/base-types/ …
Ohad Schneider

64

ทุกอย่างขึ้นอยู่กับ

การเปรียบเทียบสตริง unicode นั้นยาก:

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

ดู: http://en.wikipedia.org/wiki/Unicode_equivalence


หากคุณพยายามเปรียบเทียบ 2 ยูนิโค้ดสตริงในกรณีที่ไม่รู้สึกตัวและต้องการให้มันทำงานได้ทุกที่คุณมีปัญหาที่เป็นไปไม่ได้

ตัวอย่างคลาสสิกคือภาษาตุรกี iซึ่งเมื่อตัวพิมพ์ใหญ่กลายเป็นİ (สังเกตเห็นจุด)

โดยค่าเริ่มต้นกรอบงาน. Net มักจะใช้CurrentCultureสำหรับฟังก์ชั่นที่เกี่ยวข้องกับสตริงโดยมีข้อยกเว้นที่สำคัญมาก.Equalsซึ่งใช้การเปรียบเทียบลำดับ (ไบต์ต่อไบต์)

สิ่งนี้นำไปสู่โดยการออกแบบไปยังฟังก์ชั่นสตริงต่างๆที่ทำงานแตกต่างกันไปตามวัฒนธรรมของคอมพิวเตอร์


อย่างไรก็ตามบางครั้งเราต้องการ "จุดประสงค์ทั่วไป", การพิจารณาเล็ก ๆ น้อย ๆ , การเปรียบเทียบ

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

เพื่อให้บรรลุสิ่งนี้เรามี 3 ตัวเลือก:

  1. ตั้งค่าวัฒนธรรมอย่างชัดเจนและดำเนินการเปรียบเทียบแบบคำนึงถึงขนาดตัวพิมพ์โดยใช้กฎการเทียบเท่ายูนิโค้ด
  2. ตั้งค่าวัฒนธรรมเป็นค่าคงที่และดำเนินการเปรียบเทียบแบบไม่คำนึงถึงขนาดตัวพิมพ์โดยใช้กฎการเทียบเท่ายูนิโค้ด
  3. ใช้OrdinalIgnoreCaseซึ่งจะเป็นตัวพิมพ์ใหญ่สตริงโดยใช้ InvariantCulture แล้วทำการเปรียบเทียบแบบไบต์ต่อไบต์

Unicode กฎความเท่าเทียมมีความซับซ้อนซึ่งหมายถึงการใช้วิธีที่ 1) หรือ 2) OrdinalIgnoreCaseมีราคาแพงกว่า ความจริงที่OrdinalIgnoreCaseไม่ได้ทำการปรับให้เป็นยูนิโค้ดพิเศษหมายความว่าสตริงบางตัวที่แสดงในลักษณะเดียวกันบนหน้าจอคอมพิวเตอร์จะไม่ถูกพิจารณาว่าเหมือนกัน ตัวอย่างเช่น: "\u0061\u030a"และ"\u00e5"ทั้งสองแสดงผลå อย่างไรก็ตามในการเปรียบเทียบลำดับจะถือว่าแตกต่างกัน

สิ่งที่คุณเลือกอย่างหนักนั้นขึ้นอยู่กับแอปพลิเคชันที่คุณกำลังสร้าง

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

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

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


จะเป็นอย่างไรถ้าฉันสร้างแอปตุรกีที่จะใช้โดยผู้ใช้ชาวตุรกีเท่านั้น แต่ฉันต้องการ "ayakkabı" และ "ayakkabi" ให้เท่ากันมีวิธีไหม? เมื่อคนพิมพ์บนโทรศัพท์พวกเขาส่วนใหญ่ใช้แป้นพิมพ์ภาษาอังกฤษเป็นค่าเริ่มต้นและไม่สนใจว่าพวกเขาพิมพ์ "ı" หรือ "i"
Volkan Sen

4

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


1

มันขึ้นอยู่กับสิ่งที่คุณต้องการ แต่ฉันอายห่างจาก InvariantCulture ถ้าคุณมากแน่ใจว่าคุณจะไม่ต้องการที่จะ จำกัด รหัสสำหรับภาษาอื่น ๆ ใช้ CurrentCulture แทน

นอกจากนี้ OrdinalIgnoreCase ควรเคารพตัวเลขซึ่งอาจเป็นหรือไม่ใช่สิ่งที่คุณต้องการ


1
เคยเขียนรหัส VB6 ในสภาพแวดล้อมแบบผสมภาษาหรือไม่? คุณสามารถสร้างรหัสที่คอมไพล์บนพีซีด้วย locale ฝรั่งเศส แต่จะไม่คอมไพล์บนพีซีด้วย locale ภาษาอังกฤษเนื่องจากตัวเลขใด ๆ ที่เก็บไว้ในทรัพยากรของฟอร์มใช้รูปแบบของ locale ปัจจุบัน ฉันขอยืนยันว่าคุณต้องใช้แนวทางตรงกันข้าม: ระวังให้มากเมื่อคุณใช้วัฒนธรรมปัจจุบัน คิดอยู่เสมอว่าระบบของคุณจะยังคงทำงานหรือไม่เมื่อข้อมูลเคลื่อนย้ายระหว่างวัฒนธรรม สิ่งเดียวกันกับเขตเวลา
Wim Coenen

ฉันเห็นด้วยกับคำตอบ "มันขึ้นอยู่กับ" แม้ว่าจะไม่ได้ติดตามบิต "หมายเลขเคารพ"
Sam Saffron

-1

คำตอบที่ง่ายมากคือถ้าคุณไม่ใช้ภาษาตุรกีคุณไม่จำเป็นต้องใช้ InvariantCulture

ดูลิงค์ต่อไปนี้:

ใน C # อะไรคือความแตกต่างระหว่าง ToUpper () และ ToUpperInvariant ()


5
คำตอบนี้อาจง่าย แต่ก็ผิดมาก ภาษาตุรกี "I" เป็นเพียงตัวอย่างเท่านั้นยังมีข้อผิดพลาดที่เป็นไปได้อีกมากมาย
Ohad Schneider

ข้อผิดพลาดอะไรอีก ฉันเพิ่งรู้กรณีปัญหาของตุรกี
HelloWorld

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