ฉันจะทำการเปรียบเทียบสตริงที่ไม่สนใจขนาดตัวพิมพ์ได้อย่างไร?


217

ฉันจะทำให้บรรทัดด้านล่างเล็กตายได้อย่างไร

drUser["Enrolled"] = 
      (enrolledUsers.FindIndex(x => x.Username == (string)drUser["Username"]) != -1);

ฉันได้รับคำแนะนำก่อนหน้านี้ในวันนี้ซึ่งแนะนำให้ใช้:

x.Username.Equals((string)drUser["Username"], StringComparison.OrdinalIgnoreCase)));

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

drUser["Enrolled"] = 
      (enrolledUsers.FindIndex(x => x.Username.Equals((string)drUser["Username"], 
                                 StringComparison.OrdinalIgnoreCase)));

ทุกคนสามารถชี้ให้เห็นปัญหาได้หรือไม่


1
ข้อมูลประเภทใดควรdrUser["Enrolled"]เป็นอย่างไร ดูเหมือนว่าค่าบูลีน แต่FindIndex()ส่งกลับดัชนี หากดัชนีของผู้ใช้นั้นเป็น 0 ก็จะส่งกลับ 0 ซึ่งอาจเป็นเท็จ เมื่อใดในความเป็นจริงก็เป็นจริง Exists()วิธีการอาจจะดีกว่าในกรณีนี้
drharris

คุณแน่ใจหรือไม่ว่าไม่มีเวลาในการจัดรูปแบบหรือพื้นที่เพิ่มเติมในเขตข้อมูลหนึ่งที่ไม่ได้อยู่ในเขตข้อมูลอื่น
joshlrogers

1
ฉันขอแนะนำให้ใช้ registeredUsers.Any () แทน FindIndex (และทดสอบ)
Marc

คำตอบ:


405

นี่ไม่ใช่วิธีปฏิบัติที่ดีที่สุดใน. NET Framework (4 & +) เพื่อตรวจสอบความเท่าเทียมกัน

String.Compare(x.Username, (string)drUser["Username"], 
                  StringComparison.OrdinalIgnoreCase) == 0

ใช้สิ่งต่อไปนี้แทน

String.Equals(x.Username, (string)drUser["Username"], 
                   StringComparison.OrdinalIgnoreCase) 

MSDN แนะนำ:

  • ใช้การโอเวอร์โหลดของวิธีการ String.Equals เพื่อทดสอบว่าสองสายจะเท่ากัน
  • ใช้String.CompareและString.CompareTo วิธีการที่จะสตริงเรียงลำดับไม่ได้ที่จะตรวจสอบเพื่อความเท่าเทียมกัน

8
คุณควรใช้ไม่ได้string.Compare String.Compare
Fred

5
@ เฟรดฉันเห็นด้วย แต่คุณสามารถมีเหตุผลได้หรือไม่
Gusdor

22
@ เฟรดฉันหวังว่าจะมีเหตุผลทางเทคนิคมากกว่า 'เพราะ Stylecop พูดอย่างนั้น' ฉันพลาดอะไรไปรึเปล่า?
Gusdor

12
ไม่แตกต่างกัน string.compare กับ String.Compare, คำพ้องสตริง System.String คลาส และการเปรียบเทียบสมาชิกเป็นวิธีการขยาย @ Fred @Gusdor
Nuri YILMAZ

23
@Gusdor stringเป็นแนวปฏิบัติที่ดีกว่าStringเนื่องจากเป็นคำหลักภาษา สำหรับหนึ่งStringอาจเป็นสิ่งอื่นนอกเหนือจากSystem.Stringที่stringไม่สามารถ นอกจากนี้ยังstringรับประกันว่าจะมีอยู่มากใน C # ในขณะที่Stringเป็นส่วนหนึ่งของ. NET มากกว่า C #
เดฟ Cousineau

36

คุณควรใช้String.Compareฟังก์ชั่นแบบคงที่ดังต่อไปนี้

x => String.Compare (x.Username, (string)drUser["Username"],
                     StringComparison.OrdinalIgnoreCase) == 0

6
ไม่มีคุณควรใช้แทนString.Equals String.Compareไม่จำเป็นต้องคำนวณว่าอันไหนใหญ่กว่าเพียงแค่พวกเขาไม่เท่ากัน
ErikE

@ErikE: ฉันสงสัยว่าวิธีใดที่คุณจะแนะนำให้ใช้ในอีก 6 ปี :-)
Oleg

3
ฉันไม่สงสัยเลย! ฉันมั่นใจว่าฉันจะแนะนำให้ใช้ความเท่าเทียมกันเมื่อคุณต้องการซีแมนทิกส์เท่าเทียมกันและใช้การเปรียบเทียบเมื่อคุณต้องการซีแมนทิกส์เปรียบเทียบ มันยากขนาดไหนสำหรับเรื่องนี้? IEquatableและIComparableไม่ทำสิ่งเดียวกันและคุณสามารถมีคลาสที่ใช้งานได้ แต่จะทำให้ไม่มีเหตุผลที่จะนำสิ่งอื่นมาใช้ ตัวอย่างเช่นคุณสามารถสั่งซื้อตัวอย่างเซนเซอร์ตามเวลาโดยไม่มีสิ่งใดเทียบเท่า (IComparable) และคุณสามารถระบุได้ว่าสิ่งต่าง ๆ มีความเท่าเทียมกัน (IEquatable) แต่ก็ไม่มีเหตุผลที่จะสั่งให้พวกเขา (พูดหมายเลขประจำเครื่องคอมพิวเตอร์)
ErikE

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

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

27

โปรดใช้สิ่งนี้เพื่อการเปรียบเทียบ:

string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);

10
เพียงแค่ตระหนักถึงข้อดีและข้อผิดพลาดของการใช้ CurrentCultureIgnoreCase กับ OrdinalIgnoreCase หากคุณไม่ต้องการความหมายของการเปรียบเทียบวัฒนธรรมให้บันทึกประสิทธิภาพและใช้การเปรียบเทียบตามลำดับ
ErikE

7

คำตอบอื่น ๆ นั้นถูกต้องทั้งหมด แต่อย่างใดต้องใช้เวลาในการพิมพ์StringComparison.OrdinalIgnoreCaseและใช้งานString.Compareและยังมีการใช้

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

using System;

/// <summary>
/// String helpers.
/// </summary>
public static class StringExtensions
{
    /// <summary>
    /// Compares two strings, set ignoreCase to true to ignore case comparison ('A' == 'a')
    /// </summary>
    public static bool CompareTo(this string strA, string strB, bool ignoreCase)
    {
        return String.Compare(strA, strB, ignoreCase) == 0;
    }
}

หลังจากนั้นการเปรียบเทียบทั้งหมดจะสั้นลงประมาณ 10 ตัวอักษรโดยประมาณ - เปรียบเทียบ:

ก่อนที่จะใช้ส่วนขยายสตริง:

String.Compare(testFilename, testToStart,true) != 0

หลังจากใช้ส่วนขยายสตริง:

testFilename.CompareTo(testToStart, true)

2
ฉันไม่เห็นด้วยกับการตั้งชื่อการเปรียบเทียบเป็นฟังก์ชั่นที่รู้จักกันดีในซอฟต์แวร์ dev และคุณได้เปลี่ยนสิ่งที่มันทำ ฉันคิดว่าคุณควรคืนค่า int เช่นเปรียบเทียบหรือเปลี่ยนชื่อเป็นอย่างอื่น 'IsEqual'
Fred

7

คุณสามารถ (แม้ว่าจะมีข้อขัดแย้ง) ขยายSystem.Stringเพื่อให้วิธีส่วนขยายการเปรียบเทียบแบบไม่สนใจขนาดตัวพิมพ์:

public static bool CIEquals(this String a, String b) {
    return a.Equals(b, StringComparison.CurrentCultureIgnoreCase);
}

และใช้เป็นเช่นนี้:

x.Username.CIEquals((string)drUser["Username"]);

C # ช่วยให้คุณสามารถสร้างวิธีการขยายที่สามารถใช้เป็นไวยากรณ์ในการตอบสนองโครงการของคุณค่อนข้างมีประโยชน์ฉันพูด

ไม่ใช่คำตอบและฉันรู้ว่าคำถามนี้เก่าและแก้ไขแล้วฉันแค่ต้องการเพิ่มบิตเหล่านี้


3

ฉันคิดว่าคุณจะพบข้อมูลเพิ่มเติมในลิงค์นี้:

http://codeidol.com/community/dotnet/controlling-case-sensitivity-when-comparing-two-st/8873/

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

string lowerCase = "abc";
string upperCase = "AbC";
int caseInsensitiveResult = string.Compare(lowerCase, upperCase,
  StringComparison.CurrentCultureIgnoreCase);
int caseSensitiveResult = string.Compare(lowerCase,
  StringComparison.CurrentCulture);

ค่า caseSensitiveResult คือ -1 (บ่งชี้ว่า lowerCase คือ "น้อยกว่า" upperCase) และ caseInsensitiveResult เป็นศูนย์ (บ่งชี้ว่า lowerCase "เท่ากับ" upperCase)


1

วิธีการเกี่ยวกับการใช้StringComparison.CurrentCultureIgnoreCaseแทน?


5
-1: คำตอบนี้ไม่เพียงพอ โปรดดู @ ocean4dream ของคำตอบ: stackoverflow.com/a/13965429/109941
Jim G.

@decyclone: ​​ช้ากว่า OrdinalIgnoreCase แต่อาจเกี่ยวข้องในบางกรณี ดังนั้นฉันจะไม่ให้ -1 stackoverflow.com/questions/2749662/…
Csaba ถึง


1

ฉันต้องการเขียนวิธีการขยายสำหรับ EqualsIgnoreCase

public static class StringExtensions
{
    public static bool? EqualsIgnoreCase(this string strA, string strB)
    {
        return strA?.Equals(strB, StringComparison.CurrentCultureIgnoreCase);
    }
}

-11

คุณสามารถใช้ฟังก์ชั่น: .ToLower (); .ToUpper ();

แปลงสตริงของคุณแล้วเปรียบเทียบกับ ...

โชคดี


ฉันไม่คิดว่านี่จะแก้ปัญหาของเขาได้ โปรดทำเครื่องหมายด้วยว่าคำถามนี้มีอายุมากกว่า 4 ปีแล้ว
Vojtěch Dohnal

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

5
นี่เป็นวิธีปฏิบัติที่ไม่ดีมากเนื่องจากการจัดสรรหน่วยความจำ
Thorbjørn Lindeijer

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