InvariantCulture और ऑर्डिनल स्ट्रिंग तुलना के बीच अंतर


548

समानता के लिए c # में दो तारों की तुलना करते समय, InvariantCulture और Ordinal तुलना में क्या अंतर है?



2
उपयोग करने वालों के लिए String1.Equals(String2, StringComparison.Ordinal), आप बेहतर उपयोग करते हैं String1 == String2जो आंतरिक रूप से है String1.Equals(String2)और यह डिफ़ॉल्ट रूप से एक क्रमिक मामले-संवेदनशील तुलना है।
घासन

3
@Ghasan यकीन नहीं है कि अगर यह =="बेहतर" बनाता है , लेकिन यह a) छोटा है, b) कम स्पष्ट है कि यह वास्तव में क्या करता है और c) String1तुलना फेंकने के बिना शून्य हो सकता है a NullReferenceException
यूजीन बेरेसोवस्की

3
@ .NET फ्रेमवर्क पृष्ठ ( msdn.microsoft.com/en-us/library/… ) में स्ट्रिंग्स का उपयोग करने के लिए आधिकारिक MSDN सर्वश्रेष्ठ अभ्यास, स्पष्ट रूप से StringComparisonप्रकार निर्दिष्ट करने वाले ओवरलोड के उपयोग की अनुशंसा करता है । स्ट्रिंग तुलना के मामले में, इसका मतलब है String.Equals
ओहद श्नाइडर

3
@EugeneBeresovsky से बचने के लिए NullReferenceExceptionआप केवल स्थैतिक विधि का उपयोग कर सकते हैं String.Equals(string1, string2, StringComparison.Ordinal):।
ओहद श्नाइडर

जवाबों:


302

InvariantCulture

वर्ण क्रम (", बी, सी, ... आदि" के "मानक" सेट का उपयोग करता है। यह कुछ विशिष्ट स्थानों के विपरीत है, जो विभिन्न क्रमों में वर्णों को क्रमबद्ध कर सकते हैं ('a-with-तीव्र ', लोकेल के आधार पर 'a' से पहले या बाद में हो सकते हैं )।

क्रमवाचक

दूसरी ओर, कच्चे बाइट (एस) के मूल्यों को पूरी तरह से दिखता है जो चरित्र का प्रतिनिधित्व करते हैं।


Http://msdn.microsoft.com/en-us/library/e6883c06.aspx पर एक शानदार नमूना है जो विभिन्न StringComparison मानों के परिणाम दिखाता है। अंत में सभी तरह से, यह दिखाता है (अंश):

StringComparison.InvariantCulture:
LATIN SMALL LETTER I (U+0069) is less than LATIN SMALL LETTER DOTLESS I (U+0131)
LATIN SMALL LETTER I (U+0069) is less than LATIN CAPITAL LETTER I (U+0049)
LATIN SMALL LETTER DOTLESS I (U+0131) is greater than LATIN CAPITAL LETTER I (U+0049)

StringComparison.Ordinal:
LATIN SMALL LETTER I (U+0069) is less than LATIN SMALL LETTER DOTLESS I (U+0131)
LATIN SMALL LETTER I (U+0069) is greater than LATIN CAPITAL LETTER I (U+0049)
LATIN SMALL LETTER DOTLESS I (U+0131) is greater than LATIN CAPITAL LETTER I (U+0049)

आप देख सकते हैं कि जहाँ InvariantCulture पैदावार (U + 0069, U + 0049, U + 00131), साधारण उपज (U + 0049, U + 0069, U + 00131) है।


25
साधारण तुलना कोड बिंदुओं पर दिखती है , बाइट्स पर नहीं।
जॉय

143
मुझे लगता है कि उपयोगी जानकारी है, लेकिन वास्तव में इस सवाल का जवाब नहीं है। दो तारों की समानता का निर्धारण करते समय, क्या ऑर्डिनल के बजाय InvarintCulture का उपयोग करने का कोई कारण है? ऐसा लगता है कि InvariantCulture का उपयोग स्ट्रिंग्स को क्रमबद्ध करने के लिए किया जाएगा , और साधारणता का उपयोग समानता की जाँच के लिए किया जाना चाहिए (हमें परवाह नहीं है कि उच्चारण-एक के पहले या बाद में आता है, यह बस अलग है)। हालांकि, मैं खुद इस बिंदु से थोड़ा अनिश्चित हूं।
MPavlak

18
Msdn.microsoft.com/en-us/library/ms230117%28v=vs.90%29.aspx देखें और ध्यान दें कि स्ट्रिंग सामान्यीकरण और क्रमिक तुलना की सिफारिश की जाती है।
MPavlak

23
साधारण अधिक तेज है
डैरेन

9
सी # स्ट्रिंग कम्पैरिजन टेस्ट प्रकाशित अच्छा प्रदर्शन परीक्षण परिणाम है जो प्रत्येक अलग स्ट्रिंग तुलनात्मक तरीकों और उनके समय के प्रदर्शन को बताता है।
कुमार सी।

259

यह मायने रखता है, उदाहरण के लिए - चरित्र विस्तार नामक एक चीज है

var s1 = "Strasse";
var s2 = "Straße";

s1.Equals(s2, StringComparison.Ordinal);           //false
s1.Equals(s2, StringComparison.InvariantCulture);  //true

InvariantCultureSs वर्ण के साथ ss तक विस्तारित हो जाता है।


1
क्या यह बात किसी Ordinalऔर के बीच में भी भिन्न है InvariantCulture? यही मूल प्रश्न है।
मैथिज्स वेसल्स

3
उन लोगों के लिए जो यह नहीं जानते हैं ßकि ßकम से कम जर्मन में एक डबल एस के बराबर होना चाहिए , स्रोत: en.wikipedia.org/wiki/%C3%9F
पीटर

19
यह काफी सही नहीं है @Peter, आप जर्मन में ( ßऔर ssमैं एक देशी वक्ता हूँ) का उपयोग नहीं कर सकते हैं । ऐसे मामले हैं जहां दोनों कानूनी हैं (लेकिन अक्सर एक पुराना है / अनुशंसित नहीं है) और ऐसे मामले हैं जहां केवल एक फॉर्म की अनुमति है।
enzi

5
यह सरल उदाहरण स्पष्ट रूप से 2 तुलनाओं के बीच के अंतर को दर्शाता है। मुझे लगता है कि मैं अब यह कर रहा हूं।
ब्रायनलेग

4
इसे आजमाना था: ideone.com/j8DvDo इतना अच्छा! जर्मन में भी थोड़ा सबक। आश्चर्य है कि अब ß और ss में क्या अंतर है ...
Mzn

111

.NET फ्रेमवर्क में स्ट्रिंग्स का उपयोग करने के लिए सर्वोत्तम प्रथाओं की ओर इशारा करते हुए :

  • संस्कृति-अज्ञेय स्ट्रिंग मिलान के लिए अपने सुरक्षित डिफ़ॉल्ट के रूप में तुलना करें StringComparison.Ordinalया StringComparison.OrdinalIgnoreCaseतुलना करें ।
  • तुलना करें StringComparison.Ordinalया StringComparison.OrdinalIgnoreCaseबेहतर प्रदर्शन के लिए।
  • जब भाषाई रूप से अप्रासंगिक हो (उदाहरण के लिए, प्रतीकात्मक) तुलना के आधार पर स्ट्रिंग संचालन के बजाय गैर-भाषाई StringComparison.Ordinalया StringComparison.OrdinalIgnoreCaseमूल्यों का उपयोग करें CultureInfo.InvariantCulture

और अंत में:

  • StringComparison.InvariantCultureज्यादातर मामलों में आधार पर स्ट्रिंग ऑपरेशन का उपयोग न करें । कुछ अपवादों में से एक है जब आप भाषाई रूप से सार्थक लेकिन सांस्कृतिक रूप से अज्ञेय डेटा का उपयोग कर रहे हैं।

56

एक अन्य आसान अंतर (अंग्रेजी में जहां लहजे असामान्य हैं) यह है कि एक इनवेरिएंटकल्चर तुलना केस-असंवेदनशील द्वारा पूरे तार की तुलना करती है, और यदि आवश्यक हो (और अनुरोध किया गया) पहले अलग-अलग अक्षरों पर तुलना करने के बाद मामले से अलग हो जाता है। (आप केस-असंवेदनशील तुलना भी कर सकते हैं, निश्चित रूप से, जो मामले से अलग नहीं होगा।) सही किया गया:उच्चारण किए गए अक्षरों को समान अक्षरों का एक और स्वाद माना जाता है और स्ट्रिंग की तुलना पहले अनदेखा करने वाले लहजे और फिर उनके लिए लेखांकन से की जाती है यदि सामान्य अक्षर सभी मेल खाते हैं (बहुत अलग मामले के साथ-साथ अंत में एक मामले में असंवेदनशील तुलना में अनदेखा नहीं किया जाता है)। इस समूह ने पहले उच्चारण अंतर पर पूरी तरह से अलग होने के बजाय एक दूसरे के निकट एक ही शब्द के संस्करणों का उच्चारण किया। यह एक ऐसा क्रम है जिसे आप आम तौर पर एक शब्दकोश में पाएंगे, जिसमें पूंजीकृत शब्द उनके निचले समतुल्य समतुल्य के ठीक बगल में दिखाई देंगे, और उच्चारण किए गए अक्षर संबंधित अस्वीकार्य अक्षर के पास होंगे।

एक ऑर्डिनल तुलना संख्यात्मक चरित्र मूल्यों पर कड़ाई से तुलना करती है, पहले अंतर पर रोकती है। यह सॉर्ट किए गए अक्षरों को अक्षरों के निचले अक्षरों से पूरी तरह से अलग करता है (और उच्चारण वाले अक्षर संभवतः उन लोगों से अलग होते हैं), इसलिए बड़े अक्षरों वाले शब्द उनके लोअरकेस समतुल्य के पास कहीं नहीं छांटते।

InvariantCulture भी राजधानियों को निचले मामले से अधिक मानता है, जबकि साधारण रूप से राजधानियों को लोअरकेस से कम मानते हैं (पुराने दिनों से ASCII के एक होल्डओवर के पास कंप्यूटरों के लेटरकेस कम थे, अपरकेस अक्षर पहले आवंटित किए गए थे और इस प्रकार लोअरकेस अक्षरों की तुलना में कम मान थे बाद में जोड़ा गया)।

उदाहरण के लिए, साधारण द्वारा: "0" < "9" < "A" < "Ab" < "Z" < "a" < "aB" < "ab" < "z" < "Á" < "Áb" < "á" < "áb"

और InvariantCulture द्वारा: "0" < "9" < "a" < "A" < "á" < "Á" < "ab" < "aB" < "Ab" < "áb" < "Áb" < "z" < "Z"


मैंने इस पर एक और ध्यान दिया और इनवेरिएंटकल्चर उदाहरण और उच्चारण पात्रों की हैंडलिंग पर मेरे स्पष्टीकरण के बीच एक असंगतता पर ध्यान दिया। उदाहरण सही प्रतीत होता है, इसलिए मैंने स्पष्टीकरण को सुसंगत बनाने के लिए सही किया है। InvariantCulture तुलना पहले अलग-अलग लहजे में नहीं रुकती है और केवल एक ही अक्षर पर एक उच्चारण अंतर पर विचार करती है यदि बाकी तार उच्चारण और मामले के अलावा मेल खाते हैं। एक उच्चारण अंतर को पहले के मामले के अंतर से पहले माना जाता है, इसलिए "आबा" <"aba"।
रोब पार्कर

31

हालांकि सवाल के बारे में है समानता , त्वरित दृश्य संदर्भ के लिए, यहाँ कुछ तार के आदेश अनुसार क्रमबद्ध वहाँ idiosyncrasies के कुछ illustrating संस्कृतियों की एक जोड़ी का उपयोग कर।

Ordinal          0 9 A Ab a aB aa ab ss Ä Äb ß ä äb      
IgnoreCase       0 9 a A aa ab Ab aB ss ä Ä äb Äb ß      
--------------------------------------------------------------------
InvariantCulture 0 9 a A  ä Ä aa ab aB Ab äb Äb ss ß     
IgnoreCase       0 9 A a  Ä ä aa Ab aB ab Äb äb ß ss     
--------------------------------------------------------------------
da-DK            0 9 a A  ab aB Ab ss ß ä Ä äb Äb aa     
IgnoreCase       0 9 A a  Ab aB ab ß ss Ä ä Äb äb aa     
--------------------------------------------------------------------
de-DE            0 9 a A  ä Ä aa ab aB Ab äb Äb ß ss     
IgnoreCase       0 9 A a  Ä ä aa Ab aB ab Äb äb ss ß     
--------------------------------------------------------------------
en-US            0 9 a A  ä Ä aa ab aB Ab äb Äb ß ss     
IgnoreCase       0 9 A a  Ä ä aa Ab aB ab Äb äb ss ß     
--------------------------------------------------------------------
ja-JP            0 9 a A  ä Ä aa ab aB Ab äb Äb ß ss     
IgnoreCase       0 9 A a  Ä ä aa Ab aB ab Äb äb ss ß     

टिप्पणियों:

  • de-DE, ja-JPऔर en-USउसी तरह से क्रमबद्ध करें
  • Invariantकेवल उपरोक्त तीन संस्कृतियों से अलग ssऔर ßअलग तरह से
  • da-DK बहुत अलग तरह से
  • IgnoreCaseसभी नमूना संस्कृतियों के लिए झंडा मामलों

उपरोक्त तालिका उत्पन्न करने के लिए उपयोग किया जाने वाला कोड:

var l = new List<string>
    { "0", "9", "A", "Ab", "a", "aB", "aa", "ab", "ss", "ß",
      "Ä", "Äb", "ä", "äb", "あ", "ぁ", "ア", "ァ", "A", "亜" };

foreach (var comparer in new[]
{
    StringComparer.Ordinal,
    StringComparer.OrdinalIgnoreCase,
    StringComparer.InvariantCulture,
    StringComparer.InvariantCultureIgnoreCase,
    StringComparer.Create(new CultureInfo("da-DK"), false),
    StringComparer.Create(new CultureInfo("da-DK"), true),
    StringComparer.Create(new CultureInfo("de-DE"), false),
    StringComparer.Create(new CultureInfo("de-DE"), true),
    StringComparer.Create(new CultureInfo("en-US"), false),
    StringComparer.Create(new CultureInfo("en-US"), true),
    StringComparer.Create(new CultureInfo("ja-JP"), false),
    StringComparer.Create(new CultureInfo("ja-JP"), true),
})
{
    l.Sort(comparer);
    Console.WriteLine(string.Join(" ", l));
}

1
हम्म - ठीक है, यह अच्छा है कि आपने यह शोध किया, और अपने निष्कर्षों को पोस्ट किया, हालांकि मुझे बिल्कुल यकीन नहीं है कि आपकी बात क्या है। वैसे भी, डेनिश "सबसे महत्वपूर्ण संस्कृतियों" में से एक नहीं हो सकता है (हालांकि 5 मिलियन डेन वास्तव में उनकी संस्कृति के शौकीन हैं), लेकिन अगर आप "आ" को एक अतिरिक्त परीक्षण स्ट्रिंग के रूप में फेंकते हैं, और "दा-डीके" के रूप में एक अतिरिक्त परीक्षण संस्कृति, आपको कुछ दिलचस्प परिणाम दिखाई देंगे।
RenniePet

1
@RenniePet इसके लिए धन्यवाद। मैंने डेनिश को जोड़ा, क्योंकि यह 3 अन्य संस्कृतियों की तुलना में काफी अलग है। (जैसा कि विडंबना का संकेत देने वाले इमोटिकॉन अंग्रेजी भाषा में पढ़ने वाले वेब के रूप में अच्छी तरह से समझ में नहीं आते हैं, जैसा कि मैंने माना होगा, मैंने "सबसे महत्वपूर्ण संस्कृतियों" टिप्पणी को हटा दिया। आखिरकार, बीसीएल में वह सुविधा नहीं है CultureComparerजिसका हम उपयोग कर सकते हैं। सत्यापित करने के लिए। इस तालिका के लिए, Danishसंस्कृति (सूचना) बहुत महत्वपूर्ण हो गई है।)
यूजीन बेरेसोव्स्की

1
धन्यवाद। मुझे एहसास हुआ कि आपकी "सबसे महत्वपूर्ण संस्कृतियों" टिप्पणी को नमक के एक दाने के साथ लेने का इरादा था - यह सिर्फ इतना है कि मैंने इमोटिकॉन्स का उपयोग करने के लिए बहुत पुराना पा लिया है। मुझे लगता है कि टेक्सटिंग इतना सामान्य हो गया है कि इमोटिकॉन्स का उपयोग करना आपके चुटकुलों को समझाने के बाद की तरह है, चाहे आप उन्हें बताएं, चाहे कोई भी हंसे या नहीं। संयोग से, अन्य स्कैंडिनेवियाई संस्कृतियों (फिनिश, नॉर्वेजियन और स्वीडिश) डेनिश के समान हैं, सिवाय "आ" के बहुत विशेष हैंडलिंग के लिए - जो साबित करता है कि डेनिश बेहतर संस्कृति है, निश्चित रूप से।
RenniePet

1
लिखित मूल्य के वर्ण के अंत में विशेष अक्षरों worth (ae), ø (oe, ö), और å (aa, ä) के स्थान के कारण डेनिश मूल्य ä और aa अलग-अलग है।
ट्रेक

26

Invariant एक भाषाई रूप से उपयुक्त प्रकार की तुलना है।
ऑर्डिनल एक द्विआधारी प्रकार की तुलना है। (तेजी से) http://www.siao2.com/2004/12/29/344136.aspx
देखें


5

यहाँ एक उदाहरण है जहां स्ट्रिंग समानता समानता InvariantCultureIgnoreCase और OrdinalIgnoreCase का उपयोग करके समान परिणाम नहीं देगी:

string str = "\xC4"; //A with umlaut, Ä
string A = str.Normalize(NormalizationForm.FormC);
//Length is 1, this will contain the single A with umlaut character (Ä)
string B = str.Normalize(NormalizationForm.FormD);
//Length is 2, this will contain an uppercase A followed by an umlaut combining character
bool equals1 = A.Equals(B, StringComparison.OrdinalIgnoreCase);
bool equals2 = A.Equals(B, StringComparison.InvariantCultureIgnoreCase);

यदि आप इसे चलाते हैं, तो equals1 गलत होगा, और equals2 सही होगा।


बस एक और समान उदाहरण जोड़ने के लिए, लेकिन स्ट्रिंग शाब्दिक के साथ, यदि a="\x00e9"(ई तीव्र) और b="\x0065\x0301"(ई एक तीव्र उच्चारण के साथ संयुक्त), StringComparer.Ordinal.Equals(a, b)तो झूठे StringComparer.InvariantCulture.Equals(a, b)वापस आ जाएगा जबकि सही वापस आ जाएगा।
जॉर्ज हेलियर

2

अंतर दिखाने के लिए फैंसी यूनिकोड चार एक्समपल्स का उपयोग करने की आवश्यकता नहीं है। यहाँ एक सरल उदाहरण है जो मुझे आज पता चला जो केवल ASCII वर्णों से युक्त है, आश्चर्य की बात है।

ASCII तालिका के अनुसार, 0(0x48) सामान्य रूप से तुलना करने पर _(0x95) से छोटा होता है । InvariantCulture विपरीत कहेंगे (PowerShell कोड नीचे):

PS> [System.StringComparer]::Ordinal.Compare("_", "0")
47
PS> [System.StringComparer]::InvariantCulture.Compare("_", "0")
-1

-7

हमेशा उन स्ट्रिंग विधियों में InvariantCulture का उपयोग करने का प्रयास करें जो इसे अधिभार के रूप में स्वीकार करते हैं। InvariantCulture का उपयोग करके आप एक सुरक्षित पक्ष में हैं। कई .NET प्रोग्रामर इस कार्यक्षमता का उपयोग नहीं कर सकते हैं, लेकिन यदि आपके सॉफ़्टवेयर का उपयोग विभिन्न संस्कृतियों द्वारा किया जाएगा, तो InvariantCulture एक अत्यंत उपयोगी सुविधा है।


3
यदि आपके सॉफ़्टवेयर का उपयोग विभिन्न संस्कृतियों द्वारा नहीं किया जाएगा, तो यह ऑर्डिनल की तुलना में बहुत धीमा है।
काइल

4
मैं नीच समझ रहा था क्योंकि आप निश्चित रूप से अपनी बेहूदा प्रतिक्रिया के माध्यम से नहीं सोचते थे। यद्यपि यह सत्य का एक दाना है। यदि आपका एप्लिकेशन कई संस्कृतियों के बीच बड़े पैमाने पर फैला हुआ है ... तो निश्चित रूप से "हमेशा InvariantCulture का उपयोग करने का प्रयास करें" के आपके शुरुआती शब्द वारंट नहीं करता है? मुझे आश्चर्य है कि आप पिछले कुछ वर्षों से इस पागलपन को दूर करने के लिए, और शायद अधिक अनुभव प्राप्त करने के लिए वापस नहीं आए हैं।
सुमेरे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.