स्ट्रिंग क्यों नहीं है। एक स्थिर खाली करें?


188

.Net में String.Empty एक स्थिरांक के बजाय केवल क्यों पढ़ा जाता है? मैं सोच रहा था कि क्या किसी को पता है कि उस फैसले के पीछे तर्क क्या था।


5
यह सवाल इस एक को हल कर सकता है, संक्षिप्त उत्तर है, कोई नहीं जानता है ...
गॉर्डन मोनिका

हाँ, एरिक लिपिप्ट की प्रतिक्रिया के लिए +1, धन्यवाद!
ट्रैविस

विशेष रूप से यह देखते हुए कि Decimal.Zero कांस्टेबल है (उपयोगकर्ता के दृष्टिकोण से ...)
हामिश ग्रुबीजन

जवाबों:


148

इसके static readonlyबजाय उपयोग किए जाने वाले constकारण का उपयोग अप्रबंधित कोड के साथ उपयोग करने के कारण होता है, जैसा कि Microsoft द्वारा यहां साझा किए गए स्रोत आम भाषा इन्फिनिटी 2.0 रिलीज़ में दिखाया गया है । देखने के लिए फ़ाइल है sscli20\clr\src\bcl\system\string.cs

खाली स्थिरांक रिक्त स्ट्रिंग मान रखता है। हमें स्ट्रिंग कंस्ट्रक्टर को कॉल करने की आवश्यकता है ताकि कंपाइलर इसे शाब्दिक के रूप में चिह्नित न करे।

इसे एक शाब्दिक के रूप में चिह्नित करने का मतलब होगा कि यह एक ऐसे क्षेत्र के रूप में नहीं दिखता है जिसे हम मूल निवासी से प्राप्त कर सकते हैं।

मुझे यह जानकारी कोडप्रोजेक्ट के इस आसान लेख से मिली ।


मैं वास्तव में सराहना करूंगा यदि आप इस टिप्पणी (क्योंकि जॉन स्कीट नहीं कर सके ...) को यहां देख सकते हैं: stackoverflow.com/questions/8462697/…
gdoron

2
@gdoron: मेरा अनुमान (और यह एक अनुमान है) यह है। जब एक मूल्य को शाब्दिक (स्थिर) के रूप में परिभाषित किया जाता है, तो इसका मान उन स्थानों पर डाला जाता है जहां इसे संदर्भित किया जाता है, जबकि जब इसे शाब्दिक के रूप में परिभाषित नहीं किया जाता है, तो मूल्य के स्रोत को संदर्भित किया जाता है और वास्तविक मूल्य को रनटाइम पर पुनर्प्राप्त किया जाता है। मुझे संदेह है कि उत्तरार्द्ध यह सुनिश्चित कर सकता है कि रन के समय स्ट्रिंग का उचित मार्शेलिंग नेट और नेट के बीच होता है - अगर यह शाब्दिक था, तो शायद देशी कंपाइलर को किसी तरह शाब्दिक मान को अपने मूल कोड में खींचने की आवश्यकता होगी, जो शायद नहीं है। संभव। यह सब मेरी ओर से अनुमान है, यद्यपि।
जेफ येट्स

7
इसका मतलब यह है कि किसी को स्ट्रिंग के बजाय "" का उपयोग करना होगा, तरीकों में डिफ़ॉल्ट पैरामीटर मानों के लिए खाली। जो थोड़ा कष्टप्रद है।
निकोडेमस

17
"" मैं एक गलती की तरह दिख सकता हूं, जबकि string.Empty शो जानबूझकर इरादे दिखाता है
क्रिस्टोफर स्टीवेन्सन

3
@ जेफाइट्स मैं यह तथ्य जोड़ूंगा कि यह सुसंगत नहीं है, यह पहले से ही कष्टप्रद है। लोग बाकी कोड देखेंगे और आश्चर्य करेंगे कि "वह String.Empty के बजाय यहां" "का उपयोग क्यों कर रहा है?" मैं गंभीरता से विचार कर रहा हूं String.Emptyकि अकेले उस कारण से अब और उपयोग न करें ।
14

24

मुझे लगता है कि यहां बहुत भ्रम और बुरी प्रतिक्रियाएं हैं।

सबसे पहले, constक्षेत्र staticसदस्य हैं ( उदाहरण के सदस्य नहीं )।

सी # भाषा विनिर्देश के 10.4 स्थिरांक की जाँच करें।

भले ही स्थिरांक को स्थिर सदस्य माना जाता है, एक स्थिर-घोषणा को न तो स्थिर संशोधन की आवश्यकता होती है और न ही अनुमति होती है।

यदि public constसदस्य स्थिर हैं, तो कोई विचार नहीं कर सकता है कि एक स्थिर एक नई वस्तु बनाएगा।

इसे देखते हुए, कोड की निम्नलिखित पंक्तियाँ एक नई वस्तु के निर्माण के संबंध में ठीक वैसा ही काम करती हैं।

public static readonly string Empty = "";
public const string Empty = "";

यहाँ Microsoft से एक नोट है जो 2 के बीच का अंतर बताता है:

आसानी से पढ़ा जाने वाला कीवर्ड कॉन्स्टेबल कीवर्ड से अलग होता है। एक कांस्ट फील्ड को केवल क्षेत्र की घोषणा पर आरंभीकृत किया जा सकता है। एक घोषणा क्षेत्र को घोषणा में या एक कंस्ट्रक्टर में आरम्भ किया जा सकता है। इसलिए, उपयोग किए गए कंस्ट्रक्टर के आधार पर आसानी से विभिन्न क्षेत्रों में भिन्न मूल्य हो सकते हैं। इसके अलावा, एक कांस्टेबल क्षेत्र एक संकलित समय-स्थिरांक है, फिर भी रेडी कॉन्स्टेंट का उपयोग रनटाइम स्थिरांक के लिए किया जा सकता है, ...

इसलिए मुझे लगता है कि यहाँ एकमात्र प्रशंसनीय जवाब है जेफ़ येट्स का।


सी # के बारे में तरह के शब्दों और स्पष्टीकरण के लिए +1 कांस्टेबल और स्टैटिक पर विशेष रूप से।
जेफ़ येट्स

17
इसे पढ़कर, मैं इससे सहमत नहीं हूं const stringऔर static readonly stringयही काम करता हूं। लिंक किए गए कोड में कॉस्ट मानों को प्रतिस्थापित किया जाता है, जबकि स्थिर रीडॉनली मानों को संदर्भित किया जाता है। यदि आपके पास constलाइब्रेरी A है जो लाइब्रेरी B द्वारा उपयोग की जाती है, तो लाइब्रेरी B उस constचर के सभी संदर्भों को उसके शाब्दिक मूल्य से बदल देगा; यदि वह चर static readonlyइसके बजाय था, तो इसे संदर्भित किया जाएगा और रनटाइम पर इसका मूल्य निर्धारित किया जाएगा।
जेफ येट्स

3
पुस्तकालयों को संदर्भित करते समय जेफ की बात महत्वपूर्ण है। यदि आप A को फिर से जोड़ते हैं और इसे फिर से विभाजित करते हैं, तो B को फिर से देखे बिना , B अभी भी पुराने मूल्यों का उपयोग कर रहा होगा।
मार्क सोउल

4
String.Empty read only instead of a constant?

यदि आप किसी भी स्ट्रिंग को स्थिर बनाते हैं , तो संकलक को वास्तव में स्ट्रिंग के साथ बदल दिया जाता है , जहां आप उसे कॉल करते हैं और आप अपना कोड एक ही स्ट्रिंग के साथ भरते हैं और जब कोड रन को भी बार-बार पढ़ने की आवश्यकता होती है तो उस स्ट्रिंग को अलग मेमोरी से डेटा।

यदि आप अपने स्ट्रिंग को केवल एक ही स्थान पर पढ़ते हैं String.Empty, क्योंकि यह प्रोग्राम है, तो उसी स्ट्रिंग को केवल एक स्थान पर रखें और इसे पढ़ें, या इसे देखें - डेटा को न्यूनतम रखते हुए।

इसके अलावा यदि आप String.Empty का उपयोग कर किसी भी dll को संकलित करते हैं, और किसी भी कारण से String.Empty परिवर्तन करते हैं, तो संकलित dll किसी भी अधिक काम नहीं करेगा, क्योंकि costआंतरिक कोड वास्तव में स्ट्रिंग की एक प्रति रखने के लिए बनाते हैं। हर कॉल पर।

इस कोड को उदाहरण के लिए देखें:

public class OneName
{
    const string cConst = "constant string";
    static string cStatic = "static string";
    readonly string cReadOnly = "read only string";

    protected void Fun()
    {
        string cAddThemAll ;

        cAddThemAll = cConst;
        cAddThemAll = cStatic ;
        cAddThemAll = cReadOnly;    
    }
}

संकलक द्वारा इस प्रकार आएगा:

public class OneName
{
    // note that the const exist also here !
    private const string cConst = "constant string";
    private readonly string cReadOnly;
    private static string cStatic;

    static OneName()
    {
        cStatic = "static string";
    }

    public OneName()
    {
        this.cReadOnly = "read only string";
    }

    protected void Fun()
    {
        string cAddThemAll ;

        // look here, will replace the const string everywhere is finds it.
        cAddThemAll = "constant string";
        cAddThemAll = cStatic;
        // but the read only will only get it from "one place".
        cAddThemAll = this.cReadOnly;

    }
}

और विधानसभा कॉल

        cAddThemAll = cConst;
0000003e  mov         eax,dword ptr ds:[09379C0Ch] 
00000044  mov         dword ptr [ebp-44h],eax 
        cAddThemAll = cStatic ;
00000047  mov         eax,dword ptr ds:[094E8C44h] 
0000004c  mov         dword ptr [ebp-44h],eax 
        cAddThemAll = cReadOnly;
0000004f  mov         eax,dword ptr [ebp-3Ch] 
00000052  mov         eax,dword ptr [eax+0000017Ch] 
00000058  mov         dword ptr [ebp-44h],eax 

संपादित करें: सही टाइपो


तो, इसका मतलब यह है कि कास्ट स्ट्रिंग को हमेशा उस कास्ट वाले वर्ग के साथ तत्काल किया जाना है? ऐसा लगता है कि यह तब स्थैतिक रूप से उपयोग करने के लिए बेहतर है।
द बंकेर

@ विंडसर कुआँ बेहतर है, लेकिन आपके पास उपयोग करने के लिए सभी विकल्प हैं।
अरस्तू

> तब संकलित dll कोई भी समान काम नहीं करेगा, क्योंकि लागत अंदर के कोड को वास्तव में हर कॉल के लिए स्ट्रिंग की एक प्रति रखने के लिए बनाती है। @ अरिस्तोस यह बिल्कुल सही नहीं है। एक बार कोड संकलित करने के बाद, यह स्ट्रिंग के "कॉपी" को निष्पादन योग्य के पाठ ब्लॉक में संदर्भित किया जाएगा, और सभी कोड केवल उसी ब्लॉक मेमोरी का संदर्भ देंगे। आपने अपने दूसरे चरण में जो उल्लेख किया है वह केवल एक मध्यवर्ती कदम है।
पीटर डॉल्केन्स

@ user1533523 नोट के लिए धन्यवाद - मैं एक परीक्षण करूँगा जब मुझे इसे जांचने के लिए कुछ समय मिलेगा
Aristos

आपको वह असेंबली कोड कैसे मिला? सी # विधानसभा के लिए संकलन नहीं करता है!
jv110

0

यह उत्तर ऐतिहासिक उद्देश्यों के लिए मौजूद है।

मौलिक रूप से:

क्योंकि Stringएक वर्ग है और इसलिए एक स्थिर नहीं हो सकता।

विस्तारित चर्चा:

इस उत्तर को प्राप्त करने में बहुत से उपयोगी संवादों को अंकित किया गया, और इसे हटाने के बजाय, इस सामग्री को सीधे पुन: प्रस्तुत किया गया:

.NET में, (Java के विपरीत) स्ट्रिंग और स्ट्रिंग बिल्कुल समान हैं। और हाँ, आपके पास स्ट्रिंग शाब्दिक स्थिरांक .NET - DrJokepu Feb 3 '09 16:57 पर हो सकते हैं

क्या आप कह रहे हैं कि एक वर्ग में स्थिरांक नहीं हो सकते हैं? - स्टिंगजैक 16 फरवरी को 3 '09 को

हां, वस्तुओं को आसानी से उपयोग करना होगा। केवल संरचनाएं लगातार कर सकती हैं। मुझे लगता है कि जब आप संकलक के stringबजाय का उपयोग करते हैं तो आपके लिए Stringएक कांस्टेबल को आसानी से बदल देता है। सभी सी प्रोग्रामर को खुश रखने के साथ करते हैं। - गैरी शटलर फ़रवरी 3 '09 को 16:59 पर

tvanfosson ने बस इसे थोड़ा और क्रिया के रूप में समझाया। "एक्स एक स्थिर नहीं हो सकता है, क्योंकि युक्त वाई एक वर्ग है" बस थोड़ा सा संदर्भ-मुक्त था;) - लियोनिदास फरवरी 3 '09 17:01 पर

string.Empty स्थिर गुण है जो स्ट्रिंग क्लास का एक उदाहरण देता है, अर्थात् खाली स्ट्रिंग, न कि स्ट्रिंग क्लास। - tvanfosson फ़रवरी 3 '09 17:01 पर

खाली स्ट्रिंग कक्षा का एक सहज उदाहरण (यह एक संपत्ति नहीं है) है। - 17 फरवरी को senfo फ़रवरी 3 '09

सिर दर्द करने वाला। मुझे अब भी लगता है कि मैं सही हूं, लेकिन अब मैं कुछ कम कर रहा हूं। आज रात अनुसंधान की आवश्यकता! - गैरी शटलर फ़रवरी 3 '09 को 17:07 बजे

खाली स्ट्रिंग स्ट्रिंग क्लास का एक उदाहरण है। खाली एक स्थिर क्षेत्र है (संपत्ति नहीं, मैं सही खड़ा हूं) स्ट्रिंग वर्ग पर। मूल रूप से एक पॉइंटर और उस चीज़ के बीच का अंतर जो इसे इंगित करता है। यदि यह आसानी से नहीं होता है तो हम बदल सकते हैं कि कौन सा खाली क्षेत्र संदर्भित करता है। - 17 फरवरी को tvanfosson 3 फरवरी '09

गैरी, आपको कोई शोध करने की आवश्यकता नहीं है। इसके बारे में सोचो। स्ट्रिंग एक वर्ग है। रिक्त एक स्ट्रिंग का एक उदाहरण है। - Senfo फ़रवरी 3 '09 17:12 पर

ऐसा कुछ है जो मुझे बिल्कुल नहीं मिलता है: कैसे पृथ्वी पर स्ट्रिंग वर्ग का स्थिर निर्माता स्ट्रिंग वर्ग का एक उदाहरण बना सकता है? "चिकन या अंडा" परिदृश्य का कुछ प्रकार नहीं है? - DrJokepu फ़रवरी 3 '09 17:12 5 पर

यह उत्तर लगभग किसी अन्य वर्ग लेकिन System.String के लिए सही होगा। .NET स्ट्रिंग्स के लिए विशेष प्रदर्शन-केसिंग करता है, और उनमें से एक यह है कि आपके पास स्ट्रिंग स्थिरांक हो सकते हैं, बस इसे आज़माएं। इस मामले में, जेफ येट्स के पास सही जवाब है। - जोएल मुलर 3 फरवरी'09 को 19:25 बजे

जैसा कि described7.18 में वर्णित है, एक स्थिर-अभिव्यक्ति एक अभिव्यक्ति है जिसे पूरी तरह से संकलन-समय पर मूल्यांकन किया जा सकता है। चूंकि स्ट्रिंग के अलावा एक संदर्भ-प्रकार का गैर-शून्य मान बनाने का एकमात्र तरीका नए ऑपरेटर को लागू करना है, और चूंकि नए ऑपरेटर को निरंतर-अभिव्यक्ति में अनुमति नहीं है, इसलिए संदर्भ-प्रकारों के स्थिरांक के लिए एकमात्र संभव मूल्य स्ट्रिंग के अलावा अन्य अशक्त है। पिछली दो टिप्पणियाँ सीधे सी # भाषा विनिर्देश से ली गई थीं और जोएल मुलर ने उल्लेख किया था। - 15 फरवरी 5 बजे senfo फ़रवरी 4 '09


कृपया, सही उत्तर दें। यदि आप गोटो डेफिनिशन, आप पाएंगे कि यह स्ट्रिंग वर्ग पर है और स्ट्रिंग का एक उदाहरण है। तथ्य यह है कि यह निचले मामले के रूप में दिखाता है संकलक जादू है।
गैरी शटलर

यह मैं नहीं था जिसने आपको नीचा दिखाया लेकिन .NET में, (जावा में) स्ट्रिंग और स्ट्रिंग बिल्कुल समान हैं। और हाँ, आप स्ट्रिंग शाब्दिक स्थिरांक को .NET में रख सकते हैं
तमस Czinege

10
यह उत्तर लगभग किसी अन्य वर्ग लेकिन System.String के लिए सही होगा। .NET स्ट्रिंग्स के लिए विशेष प्रदर्शन-केसिंग करता है, और उनमें से एक यह है कि आपके पास स्ट्रिंग स्थिरांक हो सकते हैं, बस इसे आज़माएं। इस मामले में, जेफ येट्स के पास सही जवाब है।
जोएल मुएलर

7
मैंने लगभग इस उत्तर को हटा दिया क्योंकि एक बहुत बेहतर साथ आया था, लेकिन इन टिप्पणियों में चर्चा रखने लायक है।
गैरी शट्लर

1
@ गैरी, तुम खुशकिस्मत हो कि मैंने तुम्हारी आखिरी टिप्पणी पढ़ी, नहीं तो मैं भी निराश हो जाता। एक स्ट्रिंग में .NET की एक विशेष सुविधा होती है, जो कि यह एक रेफ क्लास है यह एक कास्ट हो सकती है।
शिम्मी वेइटहैंडलर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.