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.