Apakah ada kasus C # yang sama dengan operator?


156

Saya tahu bahwa yang berikut ini peka huruf besar-kecil:

if (StringA == StringB) {

Jadi adakah operator yang akan membandingkan dua string dengan cara yang tidak sensitif?



Jika seseorang menemukan pertanyaan ini untuk mencari perbandingan case-insensitive untuk Kamus <string, int>, lihat pertanyaan ini di sini: Akses case-sensitive untuk kamus umum
Robotnik

Akan sangat menyenangkan; mengatakan untuk mendefinisikan yang sesuai ~=dengan paralel ==sebagai versi case-insensitive
eidylon

Jika pengembang Microsoft melihat ini, saya pikir ada kebutuhan untuk operator case-sensitive dalam versi csharp berikutnya. String ini. Sama () panjang.
Rez.Net

Jawaban:


288

Coba ini:

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

Saya seorang pemula StackOverflow relatif - dapatkah Anda menjelaskan apa yang Anda maksud dengan menambahkan tautan? Apakah maksud Anda dengan dokumen MSDN?
John Feminella

55
Jika Anda ingin perbandingan yang peka terhadap budaya, gunakan metode ini. Jika Anda hanya ingin memastikan "FILE" dan "file" diterima, gunakan "OrdinalIgnoreCase" atau kode Anda mungkin tidak berfungsi di tempat-tempat seperti lokal Turki. Untuk info lebih lanjut, lihat moserware.com/2008/02/does-your-code-pass-turkey-test.html
Jeff Moser

10
Tidak yakin apa yang dibicarakan Samuel ... jawaban ini sempurna. Itu benar dan jelas. Tidak perlu referensi. +1
Berlayar Judo

3
Argh ini suap yang mengerikan! keyboard saya akan aus. Lewat sudah hari-hari ketika saya bisa menggunakan " if A$=B$ then goto 10"
Sanjay Manohar

9
@Sanjay Manohar Lalu tulis operator khusus - dan saya akan merekomendasikan keyboard yang lebih baik.
Rushyo

37

Cara terbaik untuk membandingkan 2 string dengan mengabaikan huruf-huruf adalah dengan menggunakan String. Metode yang sama dengan yang menentukan perbandingan string case ordinal abaikan. Ini juga merupakan cara tercepat, jauh lebih cepat daripada mengubah string menjadi huruf besar atau kecil dan membandingkannya setelah itu.

Saya menguji kinerja kedua pendekatan dan perbandingan string case ordinal Abaikan lebih dari 9 kali lebih cepat ! Ini juga lebih dapat diandalkan daripada mengubah string menjadi huruf besar atau kecil (lihat masalah Turki i). Jadi selalu gunakan metode String.Equals untuk membandingkan string untuk kesetaraan:

String.Equals(string1, string2, StringComparison.OrdinalIgnoreCase);

Jika Anda ingin melakukan perbandingan string khusus budaya Anda dapat menggunakan kode berikut:

String.Equals(string1, string2, StringComparison.CurrentCultureIgnoreCase);

Harap perhatikan bahwa contoh kedua menggunakan logika perbandingan string dari budaya saat ini, yang membuatnya lebih lambat daripada perbandingan "kasus abaikan ordinal" dalam contoh pertama, jadi jika Anda tidak memerlukan logika perbandingan string budaya tertentu dan Anda setelah kinerja maksimum, gunakan perbandingan "kasus abaikan ordinal".

Untuk informasi lebih lanjut, baca kisah lengkapnya di blog saya .


1
Jangan menyarankan ToLoweratau ToLowerInvariant: mereka membuat memori hanya untuk melakukan perbandingan, dan mereka mungkin gagal karena set karakter baru ditambahkan ke unicode. ToUppergagal karena bahasa Turki 'i', antara lain; tidak ada alasan mengapa ToLowertidak akan gagal di masa depan karena alasan yang sama.
antiduh

@antiduh, terima kasih atas komentar Anda. Sebagian besar dari kita menyadari masalah potensial ini, banyak tutorial melalui Internet memberikan Turki 'i' sebagai contoh. Seperti yang Anda lihat di posting saya, saya tidak merekomendasikan menggunakan ToLoweratau ToLowerInvariantmetode, saya hanya ingin menunjukkan betapa jauh lebih efisien String.Equalsmetode ini
Pavel Vladov

3
"Sebagian besar dari kita menyadari masalah potensial ini, banyak tutorial melalui Internet memberikan bahasa Turki 'i' sebagai contoh" - tidak cukup banyak orang, dan Anda masih menyebutnya sebagai kalimat kedua dalam jawaban Anda. Selain itu, jawaban Anda tidak menyertakan cukup pembenaran untuk tidak pernah menggunakannya - Anda cukup menyebutkan kinerja; kinerja tidak selalu menjadi prioritas utama. Akibatnya, Anda saat ini melanggar pedoman pusat bantuan; tautan ke situs eksternal baik-baik saja, tetapi Anda belum cukup meringkas konten (masalah turki 'i'). SO bukan platform iklan Anda.
antiduh

20

Ada sejumlah properti di StringComparerkelas statis yang mengembalikan pembanding untuk semua jenis sensitivitas huruf yang mungkin Anda inginkan:

StringComparer Properti

Misalnya, Anda dapat menelepon

StringComparer.CurrentCultureIgnoreCase.Equals(string1, string2)

atau

StringComparer.CurrentCultureIgnoreCase.Compare(string1, string2)

Itu sedikit lebih bersih daripada string.Equalsatau string.Comparekelebihan yang mengambil StringComparisonargumen.


15
System.Collections.CaseInsensitiveComparer

atau

System.StringComparer.OrdinalIgnoreCase

Apakah ini mempengaruhi seluruh aplikasi?
GateKiller

3
Di mana saya dapat menemukan lebih banyak info tentang ini. Apakah ini berarti saya dapat menggunakan == untuk kecocokan case-case?
GateKiller

9
string.Equals(StringA, StringB, StringComparison.CurrentCultureIgnoreCase);

8

atau

if (StringA.Equals(StringB, StringComparison.CurrentCultureIgnoreCase)) {

tetapi Anda harus yakin bahwa StringA bukan nol. Jadi mungkin lebih baik kamu gunakan:

string.Equals(StringA , StringB, StringComparison.CurrentCultureIgnoreCase);

seperti yang disarankan John

EDIT: memperbaiki bug


4

Kamu bisa memakai

if (stringA.equals(StringB, StringComparison.CurrentCultureIgnoreCase))

3

Operator? TIDAK, tapi saya pikir Anda dapat mengubah budaya Anda sehingga perbandingan string tidak peka huruf besar-kecil.

// you'll want to change this...
System.Threading.Thread.CurrentThread.CurrentCulture
// and you'll want to custimize this
System.Globalization.CultureInfo.CompareInfo

Saya yakin itu akan mengubah cara string dibandingkan oleh operator yang sama.


Ya, untuk mengatakan paling tidak itu sama sekali bukan apa yang ingin Anda lakukan kecuali jika Anda ingin semua perbandingan string menjadi case-sensitive. Tapi saya pikir itu mengubah perilaku operator yang sama.
John Leidegren

3

Berikut ini ide untuk menyederhanakan sintaks:

public class IgnoreCase
{
    private readonly string _value;

    public IgnoreCase(string s)
    {
        _value = s;
    }

    protected bool Equals(IgnoreCase other)
    {
        return this == other;
    }

    public override bool Equals(object obj)
    {
        return obj != null &&
               (ReferenceEquals(this, obj) || (obj.GetType() == GetType() && this == (IgnoreCase) obj));
    }

    public override int GetHashCode()
    {
        return _value?.GetHashCode() ?? 0;
    }

    public static bool operator ==(IgnoreCase a, IgnoreCase b)
    {
        return string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
    }

    public static bool operator !=(IgnoreCase a, IgnoreCase b)
    {
        return !(a == b);
    }

    public static implicit operator string(IgnoreCase s)
    {
        return s._value;
    }

    public static implicit operator IgnoreCase(string s)
    {
        return new IgnoreCase(s);
    }
}

Dapat digunakan seperti:

Console.WriteLine((IgnoreCase) "a" == "b"); // false
Console.WriteLine((IgnoreCase) "abc" == "abC"); // true
Console.WriteLine((IgnoreCase) "Abc" == "aBc"); // true
Console.WriteLine((IgnoreCase) "ABC" == "ABC"); // true

Meskipun saya suka sintaks penggunaan yang tampak bersih , itu agak menyesatkan ( IgnoreCasevs IgnoreCaseString) dan ambigu (Java memilih unboxing implisit vs tinju implisit jadi saya percaya ini tidak akan bekerja di Jawa dengan pemain implisit kembali ke string di sana). Dan ini menciptakan overhead memori dari 2 objek baru dengan eksekusi pohon panggilan untuk setiap perbandingan melompat ke beberapa metode panggilan bersarang untuk kasus penggunaan yang ditampilkan. Yang mengatakan, untuk sebagian besar kasus, kinerja mungkin cukup baik.
Arkaine55

Meskipun ini adalah ide yang cerdas , itu tidak benar-benar bijaksana dari perspektif rawatan. Anda secara efektif membuat jenis string pengganti alih-alih menggunakan tipe string bawaan sistem. Programmer-yang-datang-setelah tidak akan mengerti apa yang terjadi sekilas dan kemudian dia akan memaki Anda. Menggunakan string.Equals () tidak terlalu buruk dan kebanyakan orang akan mengerti apa yang dilakukannya.
ntcolonel

1

Saya sangat terbiasa mengetik di akhir metode perbandingan ini: , StringComparison.

Jadi saya membuat ekstensi.

namespace System
{   public static class StringExtension
    {
        public static bool Equals(this string thisString, string compareString,
             StringComparison stringComparison)
        {
            return string.Equals(thisString, compareString, stringComparison);
        }
    }
}

Harap perhatikan bahwa Anda harus memeriksa nol thisStringsebelum memanggil ext.


1
Apakah ini sama dengan metode bawaan ini dalam versi .NET Framework saat ini? docs.microsoft.com/en-gb/dotnet/api/…
Bernard Vander Beken

1
Tampak begitu. Sepertinya versi .net yang lebih baru sertakan sekarang.
Valamas

Tersedia sejak .NET 4.5 dan semua versi .NET Core.
Bernard Vander Beken


0
if (StringA.ToUpperInvariant() == StringB.ToUpperInvariant()) {

Orang melaporkan ToUpperInvariant () lebih cepat daripada ToLowerInvariant ().


1
Invarian mungkin merupakan ide yang buruk jika budaya saat ini atau yang diinginkan memiliki aturan khusus untuk casing atas.
OregonGhost

Apakah ini membuat salinan baru dari setiap string? Jika demikian, ide yang buruk.
cjk

1
Ini juga akan membuang pengecualian jika salah satu (atau keduanya) string adalah nol.
tvanfosson

3
Dari segi kinerja, ini bukan solusi yang baik karena Anda akan membuat 2 instance string baru di sini juga.
Frederik Gheysels

0

Jawaban yang lain benar-benar valid di sini, tetapi entah bagaimana butuh waktu untuk mengetik StringComparison.OrdinalIgnoreCasedan juga menggunakan String.Compare.

Saya telah mengkodekan metode ekstensi String sederhana, di mana Anda dapat menentukan apakah perbandingan case-sensitive atau case-sensitive dengan boolean - lihat jawaban berikut:

https://stackoverflow.com/a/49208128/2338477

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.