51

मैं एक कॉन्फ़िगरेशन फ़ाइल से एन्क्रिप्टेड प्रमाण-पत्र/कनेक्शन स्ट्रिंग पढ़ रहा हूं। Resharper मुझसे कहता है, इस लाइन पर "String.IndexOf (स्ट्रिंग) संस्कृति विशिष्ट यहाँ है":स्ट्रिंग की तुलना में स्ट्रिंग की गारंटी होने पर स्ट्रिंग तुलना वास्तव में संस्कृति के आधार पर भिन्न हो सकती है?

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); 

मूल्य मैं एम रीडिंग हमेशा "होस्ट =" होगी चाहे इस पर ऐप को तैनात किया जा सके। क्या यह वास्तव में "System.StringComparison.Ordinal" बिट जोड़ने के लिए समझदार है?

अधिक महत्वपूर्ण बात यह है कि इससे कुछ भी नुकसान हो सकता है (इसका उपयोग करने के लिए)?

उत्तर

59

बिल्कुल। प्रति MSDN (http://msdn.microsoft.com/en-us/library/d93tkzah.aspx),

इस विधि में एक शब्द (केस-संवेदी और संस्कृति के प्रति संवेदनशील) खोज वर्तमान संस्कृति का उपयोग कर प्रदर्शन करती है।

तो यदि आप इसे एक अलग संस्कृति (नियंत्रण कक्ष में क्षेत्रीय और भाषा सेटिंग्स के माध्यम से) के तहत चलाते हैं तो आपको अलग-अलग परिणाम मिल सकते हैं।

इस विशेष मामले में, आपको शायद कोई समस्या नहीं होगी, लेकिन खोज स्ट्रिंग में i फेंक दें और इसे तुर्की में चलाएं और यह संभवतः आपके दिन को बर्बाद कर देगा।

देखें MSDN: http://msdn.microsoft.com/en-us/library/ms973919.aspx

इन नए सिफारिशों और एपीआई डिफ़ॉल्ट स्ट्रिंग एपीआई के व्यवहार के बारे गुमराह मान्यताओं को दूर करने के लिए मौजूद हैं। कैनोनिकल उभरते हुए बग का उदाहरण जहां गैर-भाषाई स्ट्रिंग डेटा भाषाई रूप से व्याख्या किया गया है "तुर्की-मैं" समस्या है।

यूएस अंग्रेज़ी समेत लगभग सभी लैटिन वर्णमाला के लिए, चरित्र i (\ u0069) वर्ण I (\ u0049) का लोअरकेस संस्करण है। यह आवरण नियम ऐसी संस्कृति में प्रोग्रामिंग के लिए जल्दी से डिफ़ॉल्ट हो जाता है। हालांकि, तुर्की ("टीआर-टीआर") में, एक राजधानी "मैं एक बिंदु के साथ," चरित्र (\ u0130) मौजूद है, जो i का पूंजी संस्करण है। इसी प्रकार, तुर्की में, "मैं बिना डॉट के", या (\ u0131), जो I को कैपिटल करता है, वहां एक लोअरकेस होता है। यह व्यवहार एजेरी संस्कृति ("az") में भी होता है।

इसलिए, आम तौर पर मुझे या को कम करने के बारे में धारणाएं कम होती हैं, मैं सभी संस्कृतियों के बीच मान्य नहीं हूं। यदि स्ट्रिंग तुलना दिनचर्या के लिए डिफ़ॉल्ट ओवरलोड का उपयोग किया जाता है, तो वे संस्कृतियों के बीच भिन्नता के अधीन होंगे। गैर भाषाई डेटा के लिए, निम्न उदाहरण में, इस अवांछित परिणाम उत्पन्न कर सकते:

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)); 
मैं की तुलना के अंतर की वजह से

, तुलना के परिणाम को बदलने जब धागा संस्कृति बदल गया है। मामले के बिना

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 
+8

+1 एक उदाहरण (तुर्की) दिखाने के लिए। –

+2

इंडेक्सऑफ के मामले में कुछ भी क्यों करना है, माइक्रोसॉफ्ट सामान्य रूप से लुप्तप्राय तरीके से सब कुछ मिला रहा है जिसे वे पसंद करते हैं। उनकी गलती हमेशा सबसे जटिल पहले मान लीजिए, और चलिए एक बेहद कर्कश फैशन के साथ निम्न स्तर का रास्ता चुनने दें। –

+4

ठीक है, मामले के बारे में भूल जाओ। यदि आप अंग्रेजी के बाहर जाते हैं तो अन्य उदाहरण भी हैं। उदाहरण के लिए ई + संयोजन उच्चारण, बनाम। वे ordinal में अलग हैं, लेकिन एक ही भाषाई (संपादन देखें)। मान लीजिए, भाषा मुश्किल है। –

25

CA1309: UseOrdinalStringComparison

यह नहीं चोट करता है स्पष्ट रूप से या तो StringComparison.Ordinal या StringComparison.OrdinalIgnoreCase पैरामीटर की स्थापना करके उसका उपयोग नहीं करने के लिए, लेकिन ", अपने कोड अक्सर लाभ गति, शुद्धता बढ़ जाती है, और अधिक विश्वसनीय हो जाता है। "।


साधारण क्या है, और यह आपके मामले में क्यों मायने रखता है?

कोई कार्रवाई क्रमसूचक तरह नियमों का उपयोग करता है स्ट्रिंग में प्रत्येक चार की तुलना संख्यात्मक मान (यूनिकोड कोड बिंदु) पर आधारित प्रदर्शन करती है। एक सामान्य तुलना तेजी से है लेकिन संस्कृति-असंवेदनशील है। जब आप यूनिकोड वर्ण (यू +) से शुरू होने वाले तारों को सॉर्ट करने के लिए क्रमिक क्रम नियमों का उपयोग करते हैं, तो स्ट्रिंग यू + xxxx स्ट्रिंग यू + yyyy से पहले आता है यदि xxxx का मान संख्यात्मक रूप से कम है।

और जैसा कि आपने कहा था ... जिस स्ट्रिंग वैल्यू में आप पढ़ रहे हैं वह संस्कृति संवेदनशील नहीं है, इसलिए शब्द तुलना के विपरीत एक सामान्य तुलना का उपयोग करना समझ में आता है। बस याद रखें, साधारण का मतलब है "यह संस्कृति संवेदनशील नहीं है"।

5

अपने विशिष्ट प्रश्न का उत्तर देने के लिए: नहीं, लेकिन एक स्थिर विश्लेषण उपकरण यह महसूस करने में सक्षम नहीं होगा कि आपके इनपुट मूल्य में लोकेल-विशिष्ट जानकारी कभी नहीं होगी।