Trochę kultury!

CultureInfo

Życie programisty byłoby prostsze, gdyby zawsze używał explicite CultureInfo, gdy korzysta z ToString(). Chodzi o typy, dla których ToString() przyjmuje IFormatProvider jako parametr.

Przykładem niech będzie Double oraz DateTime.

string dateMessage = DateTime.Now.ToString(CultureInfo.InvariantCulture);
string intMessage = (72.05).ToString(CultureInfo.InvariantCulture);

Te dwa typy potrzebują jakiś IFormatProvider, nawet gdy jest wywołana bezparametrowa ToString(). Bierze go wtedy z Thread.CurrentThread.CurrentCulture.
ToString() jest często wołana niejawnie. W mniej bezpośredni sposób jest wołana wewnątrz

string.Format(string format, params object[] args);

Dlatego metoda string.Format ma też sygnaturę

string.Format(IFormatProvider provider, string format, params object[]);

która przekazuje jak mają być formatowane wszystkie obiekty, które potrzebują IFormatProvidera.

Do rzeczy

Czy często pisze się kod, gdzie jest się niepewnym jakie jest docelowe miejsce tworzonego przez nas stringa? Chyba rzadko, ale możecie mnie poprawić. Zazwyczaj gdy mamy outputować jakieś dane, to już wiemy czy idą do użytkownika czy do bazy danych.

Zdarza się za to trafić na kod, który ma wymieszane:

return intValue.ToString(CultureInfo.InvariantCulture);
// CultureInfo.CurrentCulture zwraca readonly Thread.CurrentThread.CurrentCulture
return intValue.ToString(CultureInfo.CurrentCulture); 
return intValue.ToString();

W takim, zwłaszcza cudzym, kodzie, ciężko się połapać i dotrzeć czy bezparametrowa ToString() ma implicite korzystać z CultureInfo.CurrentCulture (gdy by miała to by było explicite przekazane) czy może powinna użyć CultureInfo.InvariantCulture.

FxCop (~ VS Code Analysis) zwróci uwagę na brak CultureInfo

Kilka razy uczestniczyłem już w dyskusji, która zaczynała się od
– Czy wy stosujecie się do wszystkich reguł FxCopa?
– do większości tak, ale do tych związanych z Globalization to nie, no bo bez sensu w każdym miejscu ToString() dodawać kulturę.
Kiedyś też tak odpowiadałem, ale już mi się zmieniło. Reguły związane z Globalization są warte zachodu.

Na koniec oryginalne ostrzeżenie generowane przez VS Code Analysis:

CA1305 Specify IFormatProvider

Because the behavior of 'string.Format(string, object)' could vary based on the current user's locale settings, replace this call in 'Program.Main(string[])' with a call to 'string.Format(IFormatProvider, string, params object[])'. If the result of 'string.Format(IFormatProvider, string, params object[])' will be displayed to the user, specify 'CultureInfo.CurrentCulture' as the 'IFormatProvider' parameter. Otherwise, if the result will be stored and accessed by software, such as when it is persisted to disk or to a database, specify 'CultureInfo.InvariantCulture'.

Reklamy
Ten wpis został opublikowany w kategorii Lessons Learned i oznaczony tagami , , , , . Dodaj zakładkę do bezpośredniego odnośnika.

3 odpowiedzi na „Trochę kultury!

  1. Pingback: dotnetomaniak.pl

  2. dobrze, że zwracasz uwagę na ten problem. Przy okazji, resharper również podkreśla ToStringi i dodaje CultureInfo.InvariantCulture

    • @Arkadiusz celowo nie wspomniałem o R# bo robi to połowicznie. (1.1).ToString() jak piszesz podkreśli, ale już string.Format(„{0}”, 1.1) przepuści.
      Chyba że mam jakieś złe ustawienia R#.

Możliwość komentowania jest wyłączona.