Büyük / küçük harfe duyarlı olmayan bir dize karşılaştırması nasıl yapabilirim?


217

Aşağıdaki satırı nasıl duyarsız hale getirebilirim?

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

Bugün kullanmamı öneren bazı tavsiyeler verildi:

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

sorun şu işe yarayamıyorum, aşağıdaki satırı denedim, bu derler ama yanlış sonuçlar döndürür, kayıtlı kullanıcıları kayıtlı ve kayıtlı olmayan kullanıcılar olarak kayıtlı olarak döndürür.

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

Sorunu bilen var mı?


1
Hangi veri türü olmalı drUser["Enrolled"]? Bir boole değerine benzer, ancak FindIndex()dizini döndürür. Bu kullanıcının dizini 0 ise, yanlış olabilecek 0 döndürür. Gerçekte gerçek olduğunda. Exists()Yöntem bu durumda daha iyi olabilir.
drharris

Biçimlendirme zamanının olmadığından veya bir alanda diğerinde olmayan fazladan alan olmadığından emin misiniz?
joshlrogers

1
FindIndex (ve test) yerine enrolledUsers.Any () kullanmanızı öneririm.
Marc

Yanıtlar:


405

Bu, eşitliği kontrol etmek için .NET çerçevesindeki (4 ve +) en iyi uygulama değildir

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

Bunun yerine aşağıdakileri kullanın

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

MSDN şunları önerir:

  • İki dizenin eşit olup olmadığını sınamak için String.Equals yönteminin aşırı yüklenmesini kullanın.
  • Eşitliği denetlemek için değil, dizeleri sıralamak için String.Compare ve String.CompareTo yöntemlerini kullanın .

8
Kullanmalısın string.Compare, değil String.Compare.
Fred

5
@Fred kabul ediyorum ama sebebini kabul edebilir misiniz?
Gusdor

22
@Fred 'Stylecop öyle diyor' yerine teknik bir sebep umuyordum. Bir şey mi kaçırıyorum?
Gusdor

12
hiçbir fark string.compare with String.Compare, dize eşanlamlıları System.String sınıfı. ve üye Compare bir uzatma yöntemidir. @ Fred @Gusdor
Nuri YILMAZ

23
@Gusdor string, Stringbir dil anahtar kelimesi olduğundan daha iyi bir uygulamadır . Birincisi, Stringbaşka bir şey olabilir System.String, oysa stringolamaz. Ayrıca, stringC # 'da az çok var olduğu garanti edilirken String, teknik olarak C # yerine .NET'in bir parçasıdır.
Dave Cousineau

36

String.CompareAşağıdaki gibi statik işlev kullanmalısınız

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

6
Hayır, String.Equalsyerine kullanmalısınız String.Compare. Hangisinin daha büyük olduğunu, sadece eşit olmadıklarını hesaplamaya gerek yoktur.
ErikE

@ErikE: Merak ediyorum, 6 yıl içinde hangi yöntemi kullanmanızı önereceksiniz :-)
Oleg

3
Merak etmiyorum! Eşitlik semantiği istediğinizde eşitliği, karşılaştırma semantiği istediğinizde karşılaştırmayı kullanmanızı öneririm. Bununla ilgili bu kadar zor olan ne? IEquatableve IComparableaynı şeyi YAPMAYIN ve birini uygulayan ama diğerini uygulamak hiç mantıklı olmayacak sınıflara sahip olabilirsiniz. Örneğin, sensör örneklemelerinden herhangi biri eşit olmadan zaman ayırabilirsiniz (IComparable). Ve şeylerin eşit olup olmadığını belirtebilirsiniz (IEquatable) ancak bunları sipariş etmek mantıklı değildir (örneğin, bilgisayar seri numaraları).
ErikE

@ErikE: Benim bakış açımı anlamıyorsun. Eski cevaplar yazma zamanına karşılık gelir. Eski cevaplara dokunulmamalıdır. Çoğu ürün için doğrudur. En iyi uygulama veya performans açısından en iyi seçim daha sonra birkaç kez değiştirilebilir. Eski bir cevap hakkında tartışmanın bir anlamı yok.
Oleg

18
Özür dilerim, yorumumun doğruluğu üzerine bir eleştiri olarak aldım. Eğer söylediğiniz eski cevabınızın en iyisi olamayacağını itiraf ediyorsanız, o zaman harika! Ancak, size eski cevaplar konusunda katılmıyorum. Fakir bilgi vermek Eski cevaplar gerektiğini yorumladı edilmesi, gereken hala bildiren çünkü olması, aşağı-olarak bugünün okuyucuları.
ErikE

27

Karşılaştırma için lütfen bunu kullanın:

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

10
Sadece CurrentCultureIgnoreCase ve OrdinalIgnoreCase'i kullanmanın avantajları ve tuzaklarından haberdar olun. Kültür karşılaştırmasının semantiğine ihtiyacınız yoksa, biraz performans kaydedin ve sıralı karşılaştırma kullanın.
ErikE

7

Diğerlerinin cevabı burada tamamen geçerlidir, ancak bir şekilde yazmak StringComparison.OrdinalIgnoreCaseve kullanmak biraz zaman alır String.Compare.

Ben burada tüm kod parçacığı ekleyerek karşılaştırma büyük / küçük harf duyarlı veya boole ile anlamsız olup olmadığını belirtebilirsiniz basit String uzantısı yöntemi kodladım:

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;
    }
}

Bundan sonra tüm karşılaştırma yaklaşık 10 karakter kısalır - karşılaştırın:

Dize uzantısını kullanmadan önce:

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

Dize uzantısını kullandıktan sonra:

testFilename.CompareTo(testToStart, true)

2
Adlandırma ile aynı fikirde değilim, karşılaştırma yazılım geliştirmede iyi bilinen bir işlevdir ve temelde ne yaptığını değiştirdiniz. Bence karşılaştırmak gibi bir int döndürmelisiniz ya da adı 'IsEqual' gibi başka bir şeye değiştirmelisiniz.
Fred

7

Büyük / System.Stringküçük harf duyarlı olmayan bir karşılaştırma uzantısı yöntemi sağlamak için (tartışmalı olmasına rağmen) genişletebilirsiniz :

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

ve şu şekilde kullanın:

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

C #, projenizde sözdizimi şekeri olarak kullanılabilecek uzatma yöntemleri oluşturmanıza izin verir, oldukça yararlı olduğunu söyleyebilirim.

Cevap değil ve bu sorunun eski ve çözülmüş olduğunu biliyorum, sadece bu bitleri eklemek istedim.


3

Bu bağlantıda daha fazla bilgi bulacağınızı düşünüyorum:

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

İki dizeyi karşılaştırmak için String sınıfındaki Statik karşılaştır yöntemini kullanın. Karşılaştırmanın büyük / küçük harf duyarsız olup olmadığı, aşırı yüklenmelerinden birinin üçüncü parametresi tarafından belirlenir. Örneğin:

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

CaseSensitiveResult değeri -1'dir (lowerCase öğesinin "upperCase değerinden daha az olduğunu gösterir) ve caseInsensitiveResult değeri sıfırdır (lowerCase öğesinin" upperCase değerine eşit olduğunu gösterir).



1

EqualsIgnoreCase için bir uzantı yöntemi yazmak istiyorum

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

-11

her zaman fonksiyonları kullanabilirsiniz: .ToLower (); .ToUpper ();

dizelerinizi dönüştürün ve sonra karşılaştırın ...

İyi şanslar


Bunun sorununu çözeceğini sanmıyorum. Ayrıca bu sorunun zaten 4 yıldan daha eski olduğunu işaretleyin.
Vojtěch Dohnal

7
Bu yeni bir dize oluşturur, bu yüzden bu çok verimsiz olduğunu düşünüyorum. Bu yeni dizeyi oluşturmak için tüm karakterler kontrol edilecek ve istenen büyük / küçük harfe dönüştürülecektir, bu durumda karşılaştırma tüm karakterleri tekrar kontrol etmelidir. Böylece daha fazla bellek ve işlem gücü kullanır.
Air2

5
Bellek tahsisi nedeniyle bu çok kötü bir uygulamadır.
Thorbjørn Lindeijer

Sadece bu gereksiz bellek tahsisi ve verimsiz değildir; aynı zamanda Türkiye sınavını da geçememektedir .
dmitry
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.