2012-01-15 9 views
13

मैं StringComparison.OrdinalIgnoreCase का उपयोग कर यूआरएल पथों का परीक्षण करने के लिए स्ट्रिंग तुलना का उपयोग कर रहा हूं।स्ट्रिंग है। एक्वाल्स (string1.Substring (0, x), स्ट्रिंग 2) स्ट्रिंग 1 से बेहतर है। स्टार्ट्सविथ (स्ट्रिंग 2)?

MSDN निम्न स्ट्रिंग तुलना सलाह HERE देता है, लेकिन यह स्पष्ट नहीं है क्यों:

MSDN उदाहरण (आधे रास्ते के ऊपर पृष्ठ नीचे):

public static bool IsFileURI(string path) 
{ 
    path.StartsWith("FILE:", StringComparison.OrdinalIgnoreCase); 
    return true; 
} 

MSDN सलाह:

"हालांकि, पिछले उदाहरण समानता के परीक्षण के लिए स्ट्रिंग.StartsWith (स्ट्रिंग, स्ट्रिंग कॉम्परिसन) विधि का उपयोग करता है। क्योंकि तुलना का उद्देश्य आदेश के बजाए समानता के लिए परीक्षण करना है स्ट्रिंग्स में, एक बेहतर विकल्प बराबर विधि को कॉल करना है, जैसा कि निम्नलिखित उदाहरण में दिखाया गया है। "

public static bool IsFileURI(string path) 
{ 
    if (path.Length < 5) return false; 

    return String.Equals(path.Substring(0, 5), "FILE:", 
        StringComparison.OrdinalIgnoreCase); 
} 

प्रश्न: क्यों MSDN सुझाव है दूसरे उदाहरण बेहतर है?

चर्चा के बिंदु:

  1. जाहिर है पहले उदाहरण में return true; एक बग है और return path.StartsWith(...); होना चाहिए। हम इसे एक बग के रूप में सुरक्षित रूप से अनदेखा कर सकते हैं क्योंकि वीबी कोड सही है।

  2. समानता की तुलना करने से पहले एक सबस्ट्रिंग का निर्माण केवल स्ट्रिंग.StartsWith() को कॉल करने की तुलना में एक और मेमोरी संसाधन का उपयोग करना प्रतीत होता है।

  3. लंबाई < 5 परीक्षण एक अच्छा शॉर्ट सर्किट है, हालांकि इसका उपयोग पहले कोड के साथ ही किया जा सकता है।

  4. दूसरा उदाहरण स्पष्ट कोड के रूप में समझा जा सकता है, लेकिन मैं प्रदर्शन से चिंतित हूं। सबस्ट्रिंग का निर्माण अनावश्यक लगता है।

+4

तथ्य 'StartsWith' नमूना समारोह कोई मतलब नहीं है कि के आधार पर पारित करके सुरक्षा चिंताओं को दरकिनार कर सकता है, मैं विचार है कि के साथ जाने के लिए जा रहा हूँ नमूना मूल रूप से एक अलग फ़ंक्शन का उपयोग करता था (जैसे 'तुलनात्मक'), और किसी ने संदर्भ पर ध्यान दिए बिना नमूना को खतरनाक रूप से बदल दिया। – Gabe

+0

मुझे लगता है कि 'स्टार्टविथ' आपके इरादे को व्यक्त करने में बहुत स्पष्ट है। – I82Much

+0

@Gabe क्या आप सामान्य प्रश्न पर फिर से विचार कर सकते हैं? स्टार्ट्सविथ का उपयोग करना मेरे लिए बेहतर लगता है। तुलना के लिए एक सबस्ट्रिंग बनाना कम अच्छी तरह से प्रदर्शन करने की संभावना है। –

उत्तर

4

dotPeek का उपयोग कर StartsWith विधि को देखते हुए, यह अंततः एक आंतरिक तुलना समारोह है कि पूरी स्ट्रिंग तुलना कहता है, और रिटर्न एक बूलियन कि तुलना की वापसी मूल्य के आधार पर परिणाम:

return TextInfo.CompareOrdinalIgnoreCaseEx(this, 0, value, 0, value.Length, value.Length) == 0; 

String.Equals कॉल:

return TextInfo.CompareOrdinalIgnoreCase(this, value) == 0; 

CompareOrdinalIgnoreCase एक निजी विधि है, जो dotPeek प्रदर्शित नहीं करता है कहता है, लेकिन मेरी कूबड़ कि overlo है StartsWith द्वारा बुलाया गया विज्ञापन पूरे स्ट्रिंग को पार करता है जबकि Equals द्वारा अधिभारित अधिभार को समानता के रूप में जल्द ही निर्धारित किया जा सकता है।

यदि प्रदर्शन एक चिंता है, तो उन दोनों मानों को मापने का प्रयास करें जो आपके आवेदन के लिए सामान्य होंगे।


बाहर curiousity की, मैं दो को मापने की कोशिश की, और यह प्रतीत होता है कि Equals काफ़ी तेज है।जब मैं एक रिलीज के निर्माण का उपयोग कर नीचे कोड चलाने के लिए, Equals लगभग के रूप में तेजी से StartsWith रूप में दो बार है:

using System; 
using System.Diagnostics; 

namespace ConsoleApplication1 
{ 
    internal class Program 
    { 
     private static void Main(string[] args) 
     { 
      var url = "http://stackoverflow.com/questions/8867710/is-string-equalsstring1-substring0-x-string2-better-than-string1-startswit"; 
      var count = 10000000; 
      var http = false; 

      Stopwatch sw = Stopwatch.StartNew(); 

      for (int i = 0; i < count; i++) 
      { 
       http = url.StartsWith("http:", StringComparison.OrdinalIgnoreCase); 
      } 

      sw.Stop(); 

      Console.WriteLine("StartsWith: {0} ms", sw.ElapsedMilliseconds); 

      sw.Restart(); 

      for (int i = 0; i < count; i++) 
      { 
       http = string.Equals(url.Substring(0, 5), "http:", StringComparison.OrdinalIgnoreCase); 
      } 

      sw.Stop(); 

      Console.WriteLine("Equals: {0} ms", sw.ElapsedMilliseconds); 

      Console.ReadLine(); 
     } 
    } 
} 
+0

इसके लिए धन्यवाद! मैं कल्पना नहीं कर सकता कि क्यों 'स्टार्टविथ' अपनी तर्क की लंबाई से परे पूरी स्ट्रिंग को पार करना जारी रखेगा। इसी प्रकार, 'बराबर' समानता निर्धारित नहीं कर सकता है जब तक कि दोनों स्ट्रिंग पूरी तरह से पार न हों, जब तक कि असमानता जल्द ही नहीं मिल जाती। –

+1

@ केविनर: नहीं, 'स्टार्ट्स विथ' फ़ंक्शन आंतरिक रूप से केवल उपसर्ग की लंबाई को पार करता है। – Gabe

+2

@adrift: कारणों की तुलना में तेज़ होने की वजह सबसे अधिक संभावना है क्योंकि आप जिन तारों की तुलना कर रहे हैं वे सभी ASCII हैं (जिनके पास 'स्ट्रिंग। एक्वाल्स' में एक अनुकूलित केस है लेकिन 'स्टार्ट्स विथ' नहीं है)। यदि आप पहले 5 वर्णों में एक गैर-ASCII वर्ण का उपयोग करते हैं, तो आपको यह देखना चाहिए कि गति का लाभ गायब हो गया है। – Gabe

1

जवाब कोड उदाहरण आप Ordinal String Operations शीर्षक के अंतर्गत में प्रदान की तुरंत नीचे पाया जाता है।

.NET Framework में स्ट्रिंग्स एम्बेडेड नल वर्ण हो सकते हैं। क्रमिक और संस्कृति-संवेदनशील तुलना (तुलनात्मक संस्कृति का उपयोग करने वाली तुलना सहित तुलना) के बीच सबसे स्पष्ट अंतरों में से एक स्ट्रिंग में एम्बेडेड नल वर्णों के संचालन से संबंधित है। जब आप String.Compare और स्ट्रिंग का उपयोग करते हैं तो ये वर्णों को अनदेखा कर दिया जाता है। संस्कृति-संवेदनशील तुलना करने के लिए विधियों का उपयोग करता है (इनवेरिएंट संस्कृति का उपयोग करने वाली तुलना सहित)। नतीजतन, संस्कृति-संवेदनशील तुलना में , स्ट्रिंग्स जिसमें एम्बेडेड नल वर्ण शामिल हैं, वे स्ट्रिंग के बराबर नहीं माना जा सकता है।

महत्वपूर्ण

हालांकि स्ट्रिंग तुलना तरीकों उपेक्षा अशक्त एम्बेडेड वर्ण, इस तरह के String.Contains, String.EndsWith, String.IndexOf, String.LastIndexOf, और String.StartsWith के रूप में स्ट्रिंग खोज तरीकों नहीं है ।

कि String.StartsWith और String.Equals कि क्रमसूचक तुलना का उपयोग अलग-अलग परिणाम वापस आ जाएगी मतलब। यही है, सामान्य तुलनाओं का उपयोग करने का पूरा बिंदु सुरक्षा चिंताओं को रोकने वाली तुर्की प्रणालियों पर लोगों को रोकने के लिए था (जहां "f" != "F" मामले को अनदेखा करते समय)। मतलब किसी को अभी भी एक फ़ाइल यूआरआई कि "FIL\0E:" की तरह दिखाई देता है, तो परीक्षण का इस्तेमाल किया String.StartsWith

+2

नहीं, मुझे लगता है कि आप दोनों अनुच्छेदों को गलत तरीके से पढ़ते हैं: "... इन वर्णों [nulls] को अनदेखा किया जाता है जब आप ... संस्कृति-संवेदी तुलना करने के तरीकों का उपयोग करते हैं"। 'StringComparison.Ordinal' का उपयोग करना एक संस्कृति संवेदनशील तुलना नहीं है। इसके अलावा, "... स्ट्रिंग खोज विधियों जैसे ... प्रारंभ नहीं करता है [शून्य वर्णों को नजरअंदाज करें]"। नल के साथ समस्या 'तुलना करें' और 'बराबर' के साथ होती है, लेकिन 'स्टार्ट्स विथ' नहीं होती है। 'ऑर्डिनल 'तुलना का उपयोग करते समय न तो उपेक्षा करता है। यह मेरा लेना है और मेरे अंत में परीक्षण इसका समर्थन करता प्रतीत होता है। 'साधारण' तुलनाओं और किसी भी अन्य विचारों के महत्व को इंगित करने की सराहना करते हैं। –

+1

@ केविनआर ऐसा लगता है कि आप सही हैं। मैं मूल रूप से बाकी के सामने महत्वपूर्ण नोट पढ़ता हूं, जो कि मेरे भ्रम का स्रोत हो सकता है। – Dunes

+0

भ्रमित होने में आसान है इसलिए मैंने इस पर और अधिक तेज आंखों के लिए कहा। मुझे लगता है कि एड्रिफ्ट और गेबे ने सही विवरणों को प्रबुद्ध किया। श्रेष्ठ। –

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