2009-12-12 15 views
6

मैं निम्नलिखित चरित्र को प्रबंधित करने का प्रयास: ⨝ (http://www.fileformat.info/info/unicode/char/2a1d/index.htm)string.Empty.StartsWith (((char) 10781)। ToString()) हमेशा सच देता है?

आप की जाँच इस चरित्र के साथ शुरू है कि क्या कोई रिक्त स्ट्रिंग है, तो यह हमेशा सच देता है, यह किसी भी मतलब नहीं है! ऐसा क्यों है?

// visual studio 2008 hides lines that have this char literally (bug in visual studio?!?) so i wrote it's unicode instead. 
char specialChar = (char)10781; 
string specialString = specialChar.ToString(); 

// prints 1 
Console.WriteLine(specialString.Length); 

// prints 10781 
Console.WriteLine((int)specialChar); 

// prints false 
Console.WriteLine(string.Empty.StartsWith("A")); 

// both prints true WTF?!? 
Console.WriteLine(string.Empty.StartsWith(specialString)); 
Console.WriteLine(string.Empty.StartsWith(((char)10781).ToString())); 

उत्तर

11

आप ordinal StringComparison का उपयोग करके इस बग को ठीक कर सकते हैं:

MSDN डॉक्स से:

स्ट्रिंग तुलना गैर हो जाएगा या तो आप StringComparison.Ordinal या StringComparison.OrdinalIgnoreCase, निर्दिष्ट करते हैं -linguistic। यही है, जो भाषा के लिए विशिष्ट हैं, तुलना निर्णय लेने पर अनदेखा कर रहे हैं। इसका मतलब है कि निर्णय साधारण बाइट तुलनाओं पर आधारित हैं और आवरण को अनदेखा करते हैं और समकक्ष सारणी हैं जो संस्कृति द्वारा पैरामीटर द्वारा हैं। नतीजतन, स्पष्ट या तो StringComparison.Ordinal या StringComparison.OrdinalIgnoreCase पैरामीटर की स्थापना द्वारा के रूप में, अपने कोड अक्सर गति लाभ, शुद्धता बढ़ जाती है, और अधिक विश्वसनीय हो जाता है।

char specialChar = (char)10781; 


    string specialString = Convert.ToString(specialChar); 

    // prints 1 
    Console.WriteLine(specialString.Length); 

    // prints 10781 
    Console.WriteLine((int)specialChar); 

    // prints false 
    Console.WriteLine(string.Empty.StartsWith("A")); 

    // prints false 
    Console.WriteLine(string.Empty.StartsWith(specialString, StringComparison.Ordinal)); 
+0

संस्कृति-संवेदनशील-तुलना-दर-डिफ़ॉल्ट कम से कम आश्चर्य के सिद्धांत के एक बड़े विनाशकारी उल्लंघन की तरह लगता है। क्या अंगूठे का कोई नियम निर्धारित करने के लिए है कि किस प्रकार के तरीकों को 'सामान्य' सामान्य व्यवहार प्राप्त करने के लिए स्ट्रिंग कॉम्परिसन की आवश्यकता होती है और कौन नहीं? – bobince

+0

@ बॉबन्स- क्या आपने यह प्रश्न देखा है- http: // stackoverflow।com/प्रश्न/72,696/जो-है-आम तौर पर सबसे अच्छा के लिए उपयोग-stringcomparison-ordinalignorecase या stringcom – RichardOD

4

अच्छा यूनिकोड गड़बड़ ;-p

मुझे यकीन है कि क्यों यह ऐसा करता है नहीं कर रहा हूँ, लेकिन amusingly:

Console.WriteLine(string.Empty.StartsWith(specialString)); // true 
Console.WriteLine(string.Empty.Contains(specialString)); // false 
Console.WriteLine("abc".StartsWith(specialString)); // true 
Console.WriteLine("abc".Contains(specialString)); // false 

मेरा अनुमान है कि यह गैर-तरह एक सा व्यवहार किया जाता है चरित्र में शामिल होना Jon mentioned at devdays; कुछ स्ट्रिंग फ़ंक्शंस इसे देखते हैं, और कुछ नहीं करते हैं। और यदि यह इसे नहीं देखता है, तो यह "खाली (कुछ स्ट्रिंग) खाली स्ट्रिंग के साथ शुरू होता है", जो हमेशा सत्य है।

+0

मेरे द्वारा +1। मैंने जॉन की बात नहीं देखी थी। – RichardOD

4

इस के लिए अंतर्निहित कारण डिफ़ॉल्ट स्ट्रिंग तुलना स्थान के बारे में पता है। इसका मतलब तुलना के लिए लोकेल डेटा की सारणी का उपयोग करना (समानता समेत)।

कई (यदि अधिक नहीं हैं) यूनिकोड वर्णों के पास कई स्थानीय लोगों के लिए कोई मूल्य नहीं है, और इस प्रकार मौजूद नहीं है (या करते हैं, लेकिन कुछ भी मेल खाते हैं, या कुछ भी नहीं)।

माइकल कपलन के ब्लॉग "Sorting It All Out" पर चरित्र वजन पर प्रविष्टियां देखें। ब्लॉग्स के This series में बहुत सारी पृष्ठभूमि जानकारी है (एपीआई मूल हैं, लेकिन — जैसा कि मैं — समझता हूं .NET में तंत्र समान हैं)।

त्वरित संस्करण: यह उम्मीद करने के लिए एक जटिल क्षेत्र है (सामान्य भाषा) तुलना सही है, इससे आपकी भाषा के बाहर ग्लिफ के लिए कोड बिंदुओं के साथ विषम चीजें होती हैं।

संबंधित मुद्दे