Il metodo String.Contains è certamente una delle istruzioni più utilizzate da qualsiasi programmatore ASP.NET C# quando si tratta di compiere operazioni con stringhe di testo: sfortunatamente si tratta di un metodo che funziona in modo case-sensitive e, ad oggi, il framework non prevede (ancora) la possibilità di specificare una opzione StringComparison che consenta di cambiarne il behaviour di default.
Per ovviare a questo, la maggior parte dei programmatori si riduce a utilizzare workaround come il seguente:
1 |
sourceString.ToLower().Contains("search-word"); |
Pur trattandosi di una scorciatoia che funziona in modo corretto, la chiamata al metodo ToLower() può provocare la perdita di performance nel caso di stringhe di testo molto lunge e/o di cicli di loop particolarmente complessi. Personalmente, preferisco una soluzione più pulita e con performance migliori come quella illustrata da questo extension method:
1 2 3 4 5 6 7 8 |
/// <summary> /// Extended version of the string.Contains() method, /// accepting a [StringComparison] object to perform different kind of comparisons /// </summary> public static bool Contains(this string source, string value, StringComparison comparisonType) { return source?.IndexOf(value, comparisonType) >= 0; } |
Il metodo, come tutti gli extension method, può essere utilizzato nel seguente modo:
1 |
sourceString.Contains("Search-Word", StringComparison.InvariantCultureIgnoreCase); |
Problemi con Lingue e/o Culture diverse
Il metodo di cui sopra funzionerà senza problemi per le la lingua italiana, la lingua inglese e tutte le culture latin-based, dove le regole maiuscole e minuscole funzionano nel modo in cui siamo abituati. Questo non è vero per alcune culture specifiche, come ad esempio quella corrispondente alle lingue turche: in quei casi, la versione maiuscola della lettera "i" corrisponde a un carattere completamente diverso, ovvero "İ".
Nel caso in cui si abbia a che fare con questo tipo di culture, il metodo sopra descritto funzionerà soltanto nel caso in cui la cultura sia identica a quella con cui l'applicazione è in esecuzione - nel qual caso, l'utilizzo di StringComparison.CurrentCultureIgnoreCase sarà più che sufficiente. In tutti gli altri casi, sarà necessario adottare un approccio leggermente più complesso: la prima cosa da fare è recuperare l'oggetto CultureInfo che descrive la lingua del testo da confrontare, quindi utilizzare il metodo IndexOf fornito da quella medesima classe, nel modo seguente:
1 |
culture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0 |
Ecco come possiamo inserire tutto questo nel nostro extension method:
1 2 3 4 5 6 7 8 9 |
/// <summary> /// Extended version of the string.Contains() method, /// accepting a [CompareInfo] object to perform different kind of comparisons /// and a [CultureInfo] object instance to apply them to the given culture casing rules. /// </summary> public static bool Contains(this string source, string value, CompareOptions options, CultureInfo culture) { return culture.CompareInfo.IndexOf(source, value, options) >= 0; } |
Ed ecco come possiamo utilizzarlo:
1 |
sourceString.Contains("Search-Word", StringComparison.InvariantCultureIgnoreCase, new System.Globalization.CultureInfo("it-IT"))); |
Per il momento è tutto: è importante sottolineare che tutto quello che abbiamo detto in questo articolo, oltre a valere per il metodo Contains, si può applicare anche a tutti gli altri metodi dell'oggetto String, come Compare , Replace , StartsWith / EndsWith , e così via.
Puoi per favore presentare un esempio di come si può richiamare il secondo extension method?
Grazie
Fatto, ho aggiunto un esempio di utilizzo con un oggetto CultureInfo creato ad-hoc. Ovviamente puoi anche utilizzare CultureInfo.CurrentCulture o CultureInfo.CurrentUICulture per utilizzare la lingua predefinita impostata sul sistema.
https://docs.microsoft.com/it-it/dotnet/api/system.globalization.cultureinfo?view=netframework-4.7.2
Fammi sapere!