Resharper daje naprawdę cenne wskazówki. Nie wszystkie są oczywiste i czasami należy zagłębić się w temat. Jedną z takich wskazówek jest używanie IndexOf wraz z StringComparison.Ordinal.
Załóżmy, że mamy następujący kod:
string text = "test"; Console.WriteLine(text.IndexOf("est"));
Resharper zasugeruje konwersję do:
string text = "test"; Console.WriteLine(text.IndexOf("est", StringComparison.Ordinal));
Dlaczego?
Jeśli nie przekażemy ustawień regionalnych jawnie, wtedy domyślnie aktualna zostanie użyta.
Czasami oczywiście dokładnie tego chcemy i dlatego domyślnie przekazywany jest StringComparison.CurrentCulture.
W niektórych sytuacjach może spowodować to bardzo irytujące problemy. Każdy język ma pewne zasady, które nie zawsze pokrywają się z intuicją osoby piszącącej kod. Najsłynniejszym chyba przykładem jest język turecki i litera ‘i’.
Czego byśmy spodziewali się po poniższym kodzie?
string text = "some text this"; Console.WriteLine(text.ToUpper().IndexOf("THIS"));
Naturalne wydaje się, że po wywołaniu ToUpper, tekst “THIS” zostanie znaleziony (na pozycji 10). Zmieńmy kulturę na tr-TR (Turcja):
Thread.CurrentThread.CurrentCulture=new CultureInfo("tr-TR"); string text = "some text this"; Console.WriteLine(text.ToUpper().IndexOf("THIS"));
Na ekranie zobaczymy -1. W języku tureckim, wielka litera ‘i’ to İ, a nie ‘I’.
Inny przykład to w niemieckim litery ‘ß’ oraz ‘ss’, które będą traktowane jako takie same, jeśli ustawimy odpowiednio kulturę.
Ciekawy przykład, znalazłem również na StackOverflow:
//SOURCE: http://stackoverflow.com/a/10941507 var s1 = "é"; //é as one character (ALT+0233) var s2 = "é"; //'e', plus combining acute accent U+301 (two characters) Console.WriteLine(s1.IndexOf(s2, StringComparison.Ordinal)); //-1 Console.WriteLine(s1.IndexOf(s2, StringComparison.InvariantCulture)); //0 Console.WriteLine(s1.IndexOf(s2, StringComparison.CurrentCulture)); //0
Problem w tym, że nie mamy pojęcia na jakim komputerze nasz kod jest wykonywany. Musimy przyjmować, że może być to dowolna kultura. Jeśli zatem, porównujemy angielskie czy polskie znaki, wtedy nie chcemy korzystać z ustawień regionalnych. Co jeśli aplikacja webowa jest hostowana na niemieckim serwerze, a porównujemy w niej wyłącznie polskie słowa, bo np. baza danych i aplikacja jest wykorzystywana wyłącznie w Polsce. Z tego względu, bezpieczniejszą opcją jest StringComparison.Ordinal, która porównuje wartości liczbowe znaków (np. kod ASCII).
Krótko, zwięźle na temat. Dzięki!
Btw, masz malutką literówkę na początku “Resharper daję” 🙂
Poprawione, dzieki:)