String.ToUpper και String.ToLower: Ξεχάστε τα για να κοιμάστε ήσυχοι
Λοιπόν αυτό είναι κάτι που δεν το είχα παρατηρήσει, μέχρι που πιάσαμε την κουβέντα περί FxCop και Globalization rules.
Αν χρησιμοποιήσετε το String.ToLower ή String.ToUpper και κάνετε ανάλυση του κώδικα μέσα από το Visual Studio θα χτυπήσει το CA1304 warning
Warning 9 CA1304 : Microsoft.Globalization : Because the behavior of 'String.ToUpper()' could vary based on the current user's locale settings, replace this call in 'Module1.Main()' with a call to 'String.ToUpper(CultureInfo)'. If the result of 'String.ToUpper(CultureInfo)' will be displayed to the user, specify 'CultureInfo.CurrentCulture' as the 'CultureInfo' 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'. C:\Users\Manos\AppData\Local\Temporary Projects\ConsoleApplication1\Module1.vb 21 ConsoleApplication1
Αυτό είναι ένα unicode πρόβλημα που οφείλεται στο ότι σε πολλά cultures η μετατροπή από Lower σε Upper και ξανά σε Lower δεν είναι κυκλική! Δηλαδή αν ξεκινήσεις από ένα string πεζών, το μετατρέψεις σε κεφαλαία και ξανά σε πεζά, το πρώτο με το τρίτο string δεν είναι πάντοτε ίδια. Στα Ελληνικά υπάρχει πρόβλημα με το τελικό Σ και τα τονούμενα πεζά με διαλυτικά. Ας πούμε, το
"ΐΰ" = "ΐΰ".ToUpper.ToLower
δίνει False!
Σε άλλες γλώσσες που χρησιμοποιούν latin characters, το πρόβλημα είναι πιο έντονο (πχ βλ. εδώ σχετικά με το Τούρκικο locale).
Το πρόβλημα είναι ότι υπάρχει περίπτωση, κώδικας που παίρνει security αποφάσεις βάσει μετατροπών .ToLower και .ToUpper να μην συμπεριφερθεί σωστά. Γι αυτό καλό είναι
- Να χρησιμοποιηθεί η String.ToUpper(CultureInfo) και String.ToLower(CultureInfo)
- Να χρησιμοποιηθεί η String.Equals η οποία διαθέτει overloaded κλήση που καθορίζει το culture sensitivity
- Να χρησιμοποιηθεί η String.Compare με το IgnoreCase option
Περισσότερα για το θέμα αυτό:
http://msdn2.microsoft.com/en-us/library/bb386042.aspx
http://blogs.msdn.com/michkap/archive/2005/04/04/405174.aspx
http://msdn2.microsoft.com/en-us/library/5bz7d2f8(VS.71).aspx
Το πρόβλημα αυτό ανάγεται σε επίπεδο .NET Framework, δηλαδή είναι ανεξάρτητο γλώσσας, οπότε παίξτε by-the-book για να έχετε το κεφάλι σας ήσυχο...