क्या कोई C # केस असंवेदनशील ऑपरेटर के बराबर है?


156

मुझे पता है कि निम्नलिखित मामला संवेदनशील है:

if (StringA == StringB) {

तो क्या कोई ऑपरेटर है जो असंवेदनशील तरीके से दो तारों की तुलना करेगा?



: मामले में यह सवाल भर में किसी stumbles एक शब्दकोश <स्ट्रिंग, पूर्णांक> के लिए एक केस संवेदी तुलना की तलाश में, इस सवाल पर एक नज़र यहाँ सामान्य शब्दकोश के लिए प्रकरण असंवेदनशील पहुँच
Robotnik

यह वास्तव में अच्छा होगा; एक केस-असंवेदनशील संस्करण के रूप में ~=समानांतर से संबंधित परिभाषित करने के लिए ==
ईडीलोन

यदि Microsoft डेवलपर्स इसे देखते हैं, तो मुझे लगता है कि csharp के अगले संस्करण में केस-इनसेंसिटिव ऑपरेटर की आवश्यकता है। यह string.Equal () लंबा है।
रेज.नेट

जवाबों:


288

इसे इस्तेमाल करे:

string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);

मैं एक रिश्तेदार स्टैकऑवरफ्लो नौसिखिया हूं - क्या आप समझा सकते हैं कि लिंक जोड़ने से आपका क्या मतलब है? क्या आप MSDN डॉक्स से मतलब रखते हैं?
जॉन फेमिनेला

55
यदि आप संस्कृति के प्रति संवेदनशील तुलना चाहते हैं, तो इस विधि का उपयोग करें। यदि आप यह सुनिश्चित करना चाहते हैं कि "फ़ाइल" और "फ़ाइल" दोनों स्वीकार किए जाते हैं, तो "ऑर्डिनलइग्नोरकेस" का उपयोग करें या हो सकता है कि आपका कोड तुर्की स्थानों जैसी जगहों पर काम न करे। अधिक जानकारी के लिए, moserware.com/2008/02/does-your-code-pass-turkey-test.html
जेफ मोसर

10
शमूएल क्या बात कर रहा है, यह निश्चित नहीं ... यह जवाब एकदम सही है। इसकी सही और आत्म-व्याख्यात्मक। इसे किसी संदर्भ की आवश्यकता नहीं है। +1
नौकायन जूडो

3
अर्घ यह एक ऐसा भयानक मुंहफट है! मेरा कीबोर्ड खराब हो जाएगा। गया वो दिन जब मैं " if A$=B$ then goto 10" का उपयोग कर सकता हूं
संजय मनोहर

9
@ संजय मनोहर फिर एक कस्टम ऑपरेटर लिखते हैं - और मैं एक बेहतर कीबोर्ड की सिफारिश करूंगा।
रशियो

37

सबसे अच्छा तरीका है पत्र के मामले की अनदेखी 2 तार की तुलना करने का उपयोग है String.Equals स्थिर विधि को निर्दिष्ट एक क्रमसूचक मामले स्ट्रिंग तुलना ध्यान न दें। यह सबसे तेज़ तरीका भी है, जो स्ट्रिंग्स को लोअर या अपर केस में बदलने और उसके बाद उनकी तुलना करने से बहुत तेज़ है।

मैंने दोनों दृष्टिकोणों के प्रदर्शन का परीक्षण किया और क्रमिक अनदेखी मामले की स्ट्रिंग तुलना 9 गुना अधिक तेज थी ! यह स्ट्रिंग्स को लोअर या अपर केस में परिवर्तित करने से भी अधिक विश्वसनीय है (तुर्की मैं समस्या की जाँच करें)। तो हमेशा उपयोग String.Equals समानता के लिए तार की तुलना करने के विधि:

String.Equals(string1, string2, StringComparison.OrdinalIgnoreCase);

यदि आप एक संस्कृति विशिष्ट स्ट्रिंग प्रदर्शन करना चाहते हैं तो आप निम्नलिखित कोड का उपयोग कर सकते हैं:

String.Equals(string1, string2, StringComparison.CurrentCultureIgnoreCase);

कृपया ध्यान दें कि दूसरा उदाहरण वर्तमान संस्कृति के स्ट्रिंग तुलना तर्क का उपयोग करता है, जो इसे पहले उदाहरण में "क्रमिक उपेक्षा मामले" की तुलना में धीमा बनाता है, इसलिए यदि आपको किसी भी संस्कृति विशिष्ट स्ट्रिंग तुलना तर्क की आवश्यकता नहीं है और आप हैं अधिकतम प्रदर्शन के बाद, "ऑर्डिनल इग्नोर केस" तुलना का उपयोग करें।

अधिक जानकारी के लिए, मेरे ब्लॉग पर पूरी कहानी पढ़ें


1
सुझाव न दें ToLowerया ToLowerInvariant: वे केवल एक तुलना करने के लिए मेमोरी बनाते हैं, और वे विफल हो सकते हैं क्योंकि नए चरित्र सेट यूनिकोड में जोड़े जाते हैं। ToUpperतुर्की 'i' के कारण दूसरों के बीच में विफल रहता है; कोई कारण नहीं है कि ToLowerभविष्य में इसी तरह के कारणों के लिए असफल नहीं होगा।
मृदुला

@antiduh, आपकी टिप्पणी के लिए धन्यवाद। हम में से अधिकांश लोग इन संभावित समस्याओं से अवगत हैं, इंटरनेट पर कई ट्यूटोरियल एक उदाहरण के रूप में तुर्की को 'i' देते हैं। जैसा कि आप मेरी पोस्ट में देखते हैं, मैं उपयोग ToLowerया ToLowerInvariantविधियों की अनुशंसा नहीं करता , मैं सिर्फ यह दिखाना चाहता था कि String.Equalsविधि कितनी अधिक कुशल है।
पावेल व्लाडोव

3
"हम में से ज्यादातर लोग इन संभावित समस्याओं से अवगत हैं, इंटरनेट पर कई ट्यूटोरियल तुर्की को उदाहरण के रूप में 'मैं' देते हैं" - पर्याप्त लोग नहीं हैं, और आप अभी भी अपने जवाब में इसे दूसरे वाक्य के रूप में उल्लेख कर रहे हैं। इसके अलावा, आपके उत्तर में इसका उपयोग न करने के लिए पर्याप्त औचित्य शामिल नहीं है - आप बस प्रदर्शन का उल्लेख करते हैं; प्रदर्शन हमेशा परम प्राथमिकता नहीं है। परिणामस्वरूप, आप वर्तमान में सहायता केंद्र दिशानिर्देशों का उल्लंघन कर रहे हैं; बाहरी साइटों के लिंक ठीक हैं, लेकिन आपने सामग्री को पर्याप्त रूप से सारांशित नहीं किया है (तुर्की 'आई' समस्या)। SO आपका विज्ञापन प्लेटफ़ॉर्म नहीं है।
एंटीड्यूह

20

StringComparerस्थिर वर्ग पर कई गुण हैं जो किसी भी प्रकार की केस-संवेदनशीलता के लिए आपकी तुलना में वापसी करते हैं:

StringComparer गुण

उदाहरण के लिए, आप कॉल कर सकते हैं

StringComparer.CurrentCultureIgnoreCase.Equals(string1, string2)

या

StringComparer.CurrentCultureIgnoreCase.Compare(string1, string2)

यह एक तर्क से लेने वाले string.Equalsया string.Compareअधिभार से थोड़ा साफ है StringComparison


15
System.Collections.CaseInsensitiveComparer

या

System.StringComparer.OrdinalIgnoreCase

क्या यह पूरे आवेदन को प्रभावित करता है?
गेटकीलर

3
मुझे इस पर और जानकारी कहां मिल सकती है। क्या इसका मतलब मैं केस असंवेदनशील मैच के लिए == का उपयोग कर सकता हूं?
गेटकिलर


8

या

if (StringA.Equals(StringB, StringComparison.CurrentCultureIgnoreCase)) {

लेकिन आपको यह सुनिश्चित करने की आवश्यकता है कि स्ट्रिंगिंग अशक्त नहीं है। तो शायद बेहतर ट्यू उपयोग:

string.Equals(StringA , StringB, StringComparison.CurrentCultureIgnoreCase);

जैसा कि जॉन ने सुझाव दिया

संपादित करें: बग को ठीक किया



3

ऑपरेटर? नहीं, लेकिन मुझे लगता है कि आप अपनी संस्कृति को बदल सकते हैं ताकि स्ट्रिंग तुलना मामले के प्रति संवेदनशील न हो।

// you'll want to change this...
System.Threading.Thread.CurrentThread.CurrentCulture
// and you'll want to custimize this
System.Globalization.CultureInfo.CompareInfo

मुझे विश्वास है कि यह उस तरीके को बदल देगा जिसकी बराबरी ऑपरेटर द्वारा की जा रही है।


हां, यह कहना बहुत कम से कम यह पूरी तरह से नहीं है कि आप क्या करना चाहते हैं जब तक आप नहीं चाहते कि सभी स्ट्रिंग तुलना असंवेदनशील हो। लेकिन मुझे लगता है कि यह बराबरी ऑपरेटर के व्यवहार को बदल देता है।
जॉन लीडग्रेन

3

यहाँ एक वाक्यविन्यास को सरल बनाने का विचार है:

public class IgnoreCase
{
    private readonly string _value;

    public IgnoreCase(string s)
    {
        _value = s;
    }

    protected bool Equals(IgnoreCase other)
    {
        return this == other;
    }

    public override bool Equals(object obj)
    {
        return obj != null &&
               (ReferenceEquals(this, obj) || (obj.GetType() == GetType() && this == (IgnoreCase) obj));
    }

    public override int GetHashCode()
    {
        return _value?.GetHashCode() ?? 0;
    }

    public static bool operator ==(IgnoreCase a, IgnoreCase b)
    {
        return string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
    }

    public static bool operator !=(IgnoreCase a, IgnoreCase b)
    {
        return !(a == b);
    }

    public static implicit operator string(IgnoreCase s)
    {
        return s._value;
    }

    public static implicit operator IgnoreCase(string s)
    {
        return new IgnoreCase(s);
    }
}

उपयोग करने योग्य:

Console.WriteLine((IgnoreCase) "a" == "b"); // false
Console.WriteLine((IgnoreCase) "abc" == "abC"); // true
Console.WriteLine((IgnoreCase) "Abc" == "aBc"); // true
Console.WriteLine((IgnoreCase) "ABC" == "ABC"); // true

जबकि मुझे साफ दिखने वाला उपयोग वाक्यविन्यास पसंद है, यह थोड़ा भ्रामक ( IgnoreCaseबनाम IgnoreCaseString) और अस्पष्ट है (जावा में निहित बॉक्सिंग अव्यक्त बनाम निहित बॉक्सिंग है, तो मेरा मानना ​​है कि यह जावा में काम नहीं करेगा। इसमें निहित कलाकारों के साथ वापस काम करना होगा)। और यह प्रदर्शित उपयोग के मामले के लिए कई नेस्टेड विधि कॉल में प्रत्येक तुलना कूद के लिए कॉल ट्री निष्पादन के साथ 2 नई वस्तुओं की मेमोरी ओवरहेड बनाता है। उन्होंने कहा, ज्यादातर मामलों के लिए प्रदर्शन शायद काफी अच्छा है।
अर्केनिय55

हालांकि यह एक चतुर विचार है, यह वास्तव में एक स्थिरता के दृष्टिकोण से बुद्धिमान नहीं है। आप सिस्टम के अंतर्निहित स्ट्रिंग प्रकार का उपयोग करने के बजाय प्रभावी रूप से एक सरोगेट स्ट्रिंग प्रकार बना रहे हैं। प्रोग्रामर-उस-आने के बाद समझ में नहीं आएगा कि एक नज़र में क्या हो रहा है और फिर वह आप पर हमला करेगा। String.Equals () का उपयोग करना वास्तव में यह सब बुरा नहीं है और अधिकांश लोग समझेंगे कि यह क्या कर रहा है।
ntcolonel

1

मुझे इन तुलना विधियों के अंत में लिखने की आदत है: , StringComparison.

इसलिए मैंने एक विस्तार किया।

namespace System
{   public static class StringExtension
    {
        public static bool Equals(this string thisString, string compareString,
             StringComparison stringComparison)
        {
            return string.Equals(thisString, compareString, stringComparison);
        }
    }
}

बस ध्यान दें कि thisStringएक्सट्रा कॉलिंग से पहले आपको नल की जांच करनी होगी ।


1
क्या यह मौजूदा .NET फ्रेमवर्क संस्करणों में इस अंतर्निहित विधि के समान है? docs.microsoft.com/en-gb/dotnet/api/…
बर्नार्ड

1
ऐसा प्रतीत होता है। ऐसा लगता है कि .net के बाद के संस्करणों में अब यह शामिल है।
वलमास

.NET 4.5 और सभी .NET कोर संस्करणों के बाद से उपलब्ध है।
बर्नार्ड वेंडर बीकेन


0
if (StringA.ToUpperInvariant() == StringB.ToUpperInvariant()) {

लोग रिपोर्ट करते हैं ToUpperInvariant () ToLowerInvariant () से तेज़ है।


1
यदि वर्तमान या वांछित संस्कृति में ऊपरी आवरण के लिए विशेष नियम हैं, तो इन्वेंट्री एक बुरा विचार हो सकता है।
ओरेगॉनहोस्ट

क्या यह प्रत्येक स्ट्रिंग की एक नई प्रति बनाता है? यदि हां, तो बुरा विचार।
cjk

1
यह भी एक अपवाद फेंक देगा अगर या तो (या दोनों) तार अशक्त हैं।
तवान्फोसन

3
प्रदर्शन-वार, यह इतना अच्छा समाधान नहीं है क्योंकि आप यहां 2 नए स्ट्रिंग उदाहरण भी बनाएंगे।
फ्रेडरिक घीसेल्स

0

अन्य उत्तर पूरी तरह से यहां मान्य हैं, लेकिन किसी तरह टाइप करने StringComparison.OrdinalIgnoreCaseऔर उपयोग करने में भी कुछ समय लगता है String.Compare

मैंने सरल स्ट्रिंग एक्सटेंशन पद्धति को कोडित किया है, जहां आप यह निर्दिष्ट कर सकते हैं कि अगर तुलना संवेदनशील है या बूलियन के साथ मामला संवेदनहीन है - निम्नलिखित उत्तर देखें:

https://stackoverflow.com/a/49208128/2338477

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.