IT이야기

문자열이 변경되지 않도록 보장되는 경우 문화에 따라 문자열 비교가 실제로 다를 수 있을까?

cyworld 2021. 4. 5. 21:14
반응형

문자열이 변경되지 않도록 보장되는 경우 문화에 따라 문자열 비교가 실제로 다를 수 있습니까?


구성 파일에서 암호화 된 자격 증명 / 연결 문자열을 읽고 있습니다. Resharper는이 줄에서 "String.IndexOf (string) is culture-specific here"라고 말합니다.

if (line.Contains("host=")) {
    _host = line.Substring(line.IndexOf(
        "host=") + "host=".Length, line.Length - "host=".Length);

... 그래서 다음과 같이 변경하고 싶습니다.

if (line.Contains("host=")) {
    _host = line.Substring(line.IndexOf("host=", System.StringComparison.Ordinal) + "host=".Length, line.Length -   "host=".Length);

내가 읽고있는 값은 앱이 배포 될 수있는 위치에 관계없이 항상 "host ="입니다. 이 "System.StringComparison.Ordinal"비트를 추가하는 것이 정말 합리적입니까?

더 중요한 것은 (사용하기 위해) 어떤 것도 해칠 수 있습니까?


물론. MSDN에 따라 ( http://msdn.microsoft.com/en-us/library/d93tkzah.aspx ),

이 메서드 는 현재 문화권을 사용하여 단어 (대소 문자 구분 및 문화권 구분 ) 검색을 수행합니다.

따라서 제어판의 지역 및 언어 설정을 통해 다른 문화에서 실행하면 다른 결과를 얻을 수 있습니다.

이 특별한 경우에는 아마도 문제가 없을 것입니다.하지만 i검색 문자열 에을 던져 터키에서 실행하면 아마 하루를 망칠 것입니다.

MSDN 참조 : http://msdn.microsoft.com/en-us/library/ms973919.aspx

이러한 새로운 권장 사항 및 API는 기본 문자열 API의 동작에 대한 잘못된 가정을 완화하기 위해 존재합니다. 비 언어 문자열 데이터가 언어 적으로 해석되는 버그의 표준 예는 "터키어 I"문제입니다.

미국 영어를 포함한 거의 모든 라틴 알파벳의 경우 문자 i (\ u0069)는 문자 I (\ u0049)의 소문자 버전입니다. 이 대 / 소문자 구분 규칙은 그러한 문화에서 프로그래밍하는 누군가에게 빠르게 기본값이됩니다. 그러나 터키어 ( "tr-TR")에는 대문자 "i with a dot"문자 (\ u0130)가 있습니다. 이것은 i의 대문자 버전입니다. 마찬가지로 터키어에는 소문자 "i without a dot"또는 (\ u0131)이 있으며 I로 대문자로 표시됩니다.이 동작은 아제르 문화 ( "az")에서도 발생합니다.

따라서 일반적으로 i 대문자 또는 소문자 I에 대한 가정은 모든 문화권에서 유효하지 않습니다. 문자열 비교 루틴에 대한 기본 오버로드가 사용되는 경우 문화권간에 차이가있을 수 있습니다. 비언어적 데이터의 경우 다음 예와 같이 원하지 않는 결과가 생성 될 수 있습니다.

    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US")
Console.WriteLine("Culture = {0}",
   Thread.CurrentThread.CurrentCulture.DisplayName);
Console.WriteLine("(file == FILE) = {0}", 
   (String.Compare("file", "FILE", true) == 0));

Thread.CurrentThread.CurrentCulture = new CultureInfo("tr-TR");
Console.WriteLine("Culture = {0}",
   Thread.CurrentThread.CurrentCulture.DisplayName);
Console.WriteLine("(file == FILE) = {0}", 
   (String.Compare("file", "FILE", true) == 0));

I의 비교 차이로 인해 스레드 문화가 변경되면 비교 결과가 변경됩니다. 다음은 출력입니다.

Culture = English (United States)
(file == FILE) = True
Culture = Turkish (Turkey)
(file == FILE) = False

다음은 대소 문자가없는 예입니다.

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

CA1309 : UseOrdinalStringComparison

사용 하지 않는 것이 나쁘지않지만 " 명시 적으로 매개 변수를 StringComparison.Ordinal 또는 StringComparison.OrdinalIgnoreCase로 설정하면 코드의 속도가 빨라지고 정확성이 높아지며 더욱 안정적이됩니다. ".


서수는 정확히 무엇이며 귀하의 경우에 왜 중요합니까?

서수 정렬 규칙을 사용하는 작업은 문자열에있는 각 Char의 숫자 값 (유니 코드 코드 포인트)을 기반으로 비교를 수행합니다. 서수 비교는 빠르지 만 문화에 민감하지 않습니다. 서수 정렬 규칙을 사용하여 유니 코드 문자 (U +)로 시작하는 문자열을 정렬 할 때 xxxx의 값이 숫자 적으로 yyyy보다 작은 경우 문자열 U + xxxx가 문자열 U + yyyy 앞에옵니다.

그리고 언급했듯이 ... 읽고있는 문자열 값은 문화권에 민감하지 않으므로 Word 비교와 반대로 서수 비교를 사용하는 것이 좋습니다. 서수는 "이것은 문화에 민감하지 않다"는 의미입니다.


특정 질문에 답하려면 : 아니요,하지만 정적 분석 도구는 입력 값에 로케일 특정 정보가 포함되지 않는다는 사실을 인식 할 수 없습니다.

ReferenceURL : https://stackoverflow.com/questions/10941375/could-string-comparisons-really-differ-based-on-culture-when-the-string-is-guara

반응형