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?

GateKiller
sumber
mungkin duplikat dari Caselessly membandingkan string dalam C #
nawfal
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);
John Feminella
sumber
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 .

Pavel Vladov
sumber
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.

Ryan Lundy
sumber
15
System.Collections.CaseInsensitiveComparer

atau

System.StringComparer.OrdinalIgnoreCase
leppie
sumber
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);
Erick
sumber
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

Grzenio
sumber
4

Kamu bisa memakai

if (stringA.equals(StringB, StringComparison.CurrentCultureIgnoreCase))
Andy Mikula
sumber
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.

John Leidegren
sumber
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
renouve
sumber
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.

Valamas
sumber
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
string.Compare(string1, string2, true)
pengguna25623
sumber
0
if (StringA.ToUpperInvariant() == StringB.ToUpperInvariant()) {

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

knoopx
sumber
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

TarmoPikaro
sumber