रिक्त स्ट्रिंग के बजाय स्ट्रिंग प्रकार के डिफ़ॉल्ट मान क्यों है?


218

इससे nullपहले कि मैं सुरक्षित तरीके से लागू कर सकूं ToUpper(), StartWith()आदि के लिए मेरे सभी तार का परीक्षण करना काफी कष्टप्रद है ...

यदि डिफ़ॉल्ट मान stringखाली स्ट्रिंग था, तो मुझे परीक्षण नहीं करना होगा, और मुझे लगता है कि यह अन्य मूल्य प्रकारों के साथ intया doubleउदाहरण के लिए अधिक सुसंगत होगा । इसके अतिरिक्त Nullable<String>समझदारी होगी।

तो सी # के डिजाइनरों nullने स्ट्रिंग्स के डिफ़ॉल्ट मूल्य के रूप में उपयोग करने का चयन क्यों किया ?

नोट: यह इस प्रश्न से संबंधित है , लेकिन इसके बजाय इसके साथ क्या करना है, इस पर अधिक ध्यान केंद्रित किया गया है।


53
क्या आप इसे अन्य संदर्भ प्रकारों के लिए एक समस्या मानते हैं?
जॉन स्कीट

17
@JonSkeet नहीं, लेकिन केवल इसलिए कि मैंने शुरू में, गलत तरीके से सोचा था कि तार मूल्य प्रकार हैं।
मार्सेल

21
@ मार्सेल: इसके बारे में सोचने का एक बहुत अच्छा कारण है।
टीजे क्राउडर

7
@JonSkeet हां। अरे हाँ। (लेकिन आप गैर-अशांत संदर्भ प्रकार चर्चा के लिए कोई अजनबी नहीं हैं ...)
कोनराड रूडोल्फ

7
मेरा मानना ​​है कि आपके पास बहुत बेहतर समय होगा यदि आप अपने स्ट्रिंग्स पर उन स्थानों पर जोर देते थे जहां आप उनसे अपेक्षा नहीं करते हैं null(और मैं यह भी सलाह देता हूं कि आप वैचारिक रूप से व्यवहार करें nullऔर स्ट्रिंग्स को अलग-अलग चीजों के रूप में देखें)। एक अशक्त मूल्य कहीं न कहीं एक त्रुटि का परिणाम हो सकता है, जबकि एक खाली स्ट्रिंग को एक अलग अर्थ देना चाहिए।
डाइगोराइमेन्डेज़

जवाबों:


312

रिक्त स्ट्रिंग के बजाय स्ट्रिंग प्रकार के डिफ़ॉल्ट मान क्यों है?

क्योंकि stringएक संदर्भ प्रकार है और सभी संदर्भ प्रकारों के लिए डिफ़ॉल्ट मान है null

इससे पहले कि मैं सुरक्षित रूप से ToUpper (), StartWith () आदि के तरीकों को लागू करने के लिए अशक्त के लिए मेरे सभी तारों का परीक्षण करने के लिए यह काफी कष्टप्रद है ...

यह संदर्भ प्रकारों के व्यवहार के अनुरूप है। अपने उदाहरण के सदस्यों को आमंत्रित करने से पहले, किसी को अशक्त संदर्भ के लिए एक चेक रखना चाहिए।

यदि स्ट्रिंग का डिफ़ॉल्ट मान खाली स्ट्रिंग था, तो मुझे परीक्षण नहीं करना होगा, और मुझे लगता है कि यह उदाहरण के लिए int या double जैसे अन्य मान प्रकारों के साथ अधिक सुसंगत होगा।

डिफ़ॉल्ट मान निर्दिष्ट करने के लिए एक विशिष्ट संदर्भ प्रकार के अलावा अन्य nullइसे असंगत बना देगा ।

इसके अतिरिक्त Nullable<String>समझदारी होगी।

Nullable<T>मान प्रकार के साथ काम करता है। ध्यान दें कि तथ्य यह है कि Nullableमूल .NET प्लेटफ़ॉर्म पर पेश नहीं किया गया था, इसलिए बहुत सारे टूटे हुए कोड थे जो उन्होंने उस नियम को बदल दिया था। ( सौजन्य @jcolebrand )


10
@HenkHolterman एक पूरे टन की चीजों को लागू कर सकता है, लेकिन इस तरह की चमकदार असंगति का परिचय क्यों?

4
@delnan - "क्यों" यहाँ सवाल था।
हेंक होल्टरमैन

8
@HenkHolterman और "संगति" आपकी बात का खंडन है "स्ट्रिंग को अन्य संदर्भ प्रकारों के विपरीत माना जा सकता है"।

6
@ डायलेन: एक ऐसी भाषा पर काम करना, जो स्ट्रिंग को वैल्यू टाइप मानती है और डॉटनेट पर 2+ साल काम करती है, मैं हेनक से सहमत हूं। मैं इसे डॉटनेट पर एक प्रमुख फ्लैव के रूप में देखता हूं ।
फैब्रिकियो अरुजो

1
@ डायलेन: एक मूल्य प्रकार बना सकता है जो अनिवार्य रूप से व्यवहार करता है, जैसे String(1) को छोड़कर, मूल्य-प्रकार-ईश व्यवहार एक प्रयोग करने योग्य डिफ़ॉल्ट मूल्य है, और (2) बॉक्सिंग अप्रत्यक्ष की एक दुर्भाग्यपूर्ण अतिरिक्त परत किसी भी समय इसे डाली गई थी। Object। यह देखते हुए कि ढेर का प्रतिनिधित्व stringअद्वितीय है, अतिरिक्त मुक्केबाजी से बचने के लिए विशेष उपचार होने से बहुत अधिक खिंचाव नहीं होगा (वास्तव में, गैर-डिफ़ॉल्ट मुक्केबाजी व्यवहार को निर्दिष्ट करने में सक्षम होना अन्य प्रकारों के लिए भी अच्छी बात होगी)।
सुपरकैट

40

हबीब सही है - क्योंकि stringएक संदर्भ प्रकार है।

लेकिन इससे भी महत्वपूर्ण बात यह है कि nullआपको इसका उपयोग करने के लिए हर बार जांच नहीं करनी होगी । आप शायद फेंक देना चाहिए ArgumentNullExceptionअगर कोई आपके फ़ंक्शन को एक nullसंदर्भ देता है, हालांकि।

यहाँ बात है - NullReferenceExceptionयदि आप .ToUpper()एक स्ट्रिंग पर कॉल करने की कोशिश करते हैं तो फ्रेमवर्क आपके लिए वैसे भी फेंक देगा । याद रखें कि यह मामला तब भी हो सकता है जब आप nullअपने फ़ंक्शन के लिए पास की गई वस्तुओं पर किसी भी संपत्ति या विधि के लिए अपने तर्कों का परीक्षण करते हैं, क्योंकि मापदंडों का मूल्यांकन किया जा सकता है null

किया जा रहा है ने कहा कि, रिक्त स्ट्रिंग या nulls के लिए जाँच करने के लिए एक आम बात है, वे प्रदान करते हैं ताकि String.IsNullOrEmpty()और String.IsNullOrWhiteSpace()सिर्फ इस उद्देश्य के लिए।


30
आपको खुद को कभी भी फेंकना नहीं चाहिए NullReferenceException( msdn.microsoft.com/en-us/library/ms173163.aspx ); आप फेंक देते हैं ArgumentNullExceptionयदि आपकी विधि शून्य रेफल्स को स्वीकार नहीं कर सकती है। जब आप समस्याएँ ठीक कर रहे होते हैं, तो निदान के लिए NullRef आमतौर पर अधिक कठिन अपवादों में से एक है, इसलिए मुझे नहीं लगता कि null की जाँच नहीं करने की अनुशंसा बहुत अच्छी है।
एंडी

3
@Andy "NullRef आम तौर पर निदान करने के लिए सबसे कठिन अपवादों में से एक है" मैं दृढ़ता से असहमत हूं, यदि आप सामान को लॉग करते हैं तो इसे ढूंढना और ठीक करना बहुत आसान है (बस अशक्त मामले को संभालना)।
लुई कोट्टमन

6
ArgumentNullExceptionपैरामीटर नाम प्रदान करने में सक्षम होने का अतिरिक्त लाभ फेंकना है। डीबगिंग के दौरान, यह सहेजता है ... इरेट, सेकंड्स। लेकिन महत्वपूर्ण सेकंड।
कोस

2
@DaveMarkle आप IsNullOrWhitespace को भी msdn.microsoft.com/en-us/library/…
Nathan Koop

1
मुझे सच में लगता है कि हर जगह अशक्त होने की जाँच अपार कोड ब्लोट का एक स्रोत है। यह बदसूरत है, और यह हिकी लग रहा है और लगातार रहना मुश्किल है। मुझे लगता है (कम से कम C # जैसी भाषाओं में) एक अच्छा नियम है "उत्पादन कोड में अशक्त कीवर्ड को प्रतिबंधित करना, परीक्षण कोड में पागल की तरह उपयोग करना"।
सारा

24

आप एक विस्तार विधि लिख सकते हैं (इसके लायक क्या है):

public static string EmptyNull(this string str)
{
    return str ?? "";
}

अब यह सुरक्षित रूप से काम करता है:

string str = null;
string upper = str.EmptyNull().ToUpper();

100
लेकिन कृपया नहीं। आखिरी चीज जो एक और प्रोग्रामर देखना चाहता है वह कोड की हजारों पंक्तियां है। सभी के साथ .EmptyNull () हर जगह सिर्फ इसलिए क्योंकि पहला लड़का अपवादों से "डरा हुआ" था।
डेव मार्कल

15
@DaveMarkle: लेकिन जाहिर है कि यह वही है जो ओपी देख रहा था। "इससे पहले कि मैं सुरक्षित रूप से ToUpper (), StartWith () आदि जैसे तरीकों को लागू करने के लिए अशक्त के लिए अपने सभी तारों का परीक्षण करने के लिए काफी परेशान हूं
टिम श्मेल्टर

19
टिप्पणी ओपी की थी, आपकी नहीं। जबकि आपका उत्तर स्पष्ट रूप से सही है, एक प्रोग्रामर जो बेसिक सवाल पूछ रहा है जैसे कि यह वास्तव में आपके समाधान को WIDE अभ्यास में डालने के खिलाफ बहुत सावधानी बरतनी चाहिए, जैसा कि अक्सर उनका अभ्यस्त है। आपके जवाब पर चर्चा नहीं करने वाले कई ट्रेडऑफ हैं, जैसे कि अपारदर्शिता, बढ़ी हुई जटिलता, रीफैक्टरिंग की कठिनाई, विस्तार के तरीकों का संभावित अति प्रयोग, और हां, प्रदर्शन। कभी-कभी (कई बार) एक सही उत्तर सही रास्ता नहीं है, और यही कारण है कि मैंने टिप्पणी की।
डेव मार्कल

5
@ ऑंडी: सही तरीके से नल चेकिंग न करने का उपाय है, ठीक से नल की जांच करना, किसी समस्या पर बैंड-सहायता नहीं लगाना।
डेव मार्कल

7
यदि आप लेखन की परेशानी से गुज़र रहे हैं .EmptyNull(), (str ?? "")तो इसकी आवश्यकता के बजाय बस उपयोग क्यों करें ? उस ने कहा, मैं @ डेवर्मकल की टिप्पणी में व्यक्त भावना से सहमत हूं: आपको शायद ऐसा नहीं करना चाहिए। nullऔर String.Emptyवैचारिक रूप से अलग हैं, और आप जरूरी एक दूसरे के समान व्यवहार नहीं कर सकते।
बजे एक CVn

17

आप C # 6.0 के रूप में भी निम्नलिखित का उपयोग कर सकते हैं

string myString = null;
string result = myString?.ToUpper();

स्ट्रिंग परिणाम शून्य होगा।


1
सही होने के लिए, c # 6.0 के बाद से, IDE के संस्करण का इससे कोई लेना-देना नहीं है क्योंकि यह एक भाषा सुविधा है।
Stijn Van Antwerpen

3
एक अन्य विकल्प -public string Name { get; set; } = string.Empty;
जाजा हैरिस

इसे क्या कहा जाता है? ? myString .ToUpper ();
हंटर नेल्सन

1
इसे नल-सशर्त संचालक कहा जाता है। आप इसके बारे में यहाँ पढ़ सकते हैं msdn.microsoft.com/en-us/magazine/dn802602.aspx
russelrillema

14

खाली स्ट्रिंग्स और नल मूल रूप से अलग हैं। एक शून्य मान का अभाव है और एक रिक्त स्ट्रिंग एक मान है जो रिक्त है।

एक चर के "मूल्य" के बारे में धारणा बनाने वाली प्रोग्रामिंग भाषा, इस मामले में एक खाली स्ट्रिंग, किसी अन्य मान के साथ स्ट्रिंग को initiazing के रूप में अच्छा होगा जो एक शून्य संदर्भ समस्या का कारण नहीं होगा।

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

एक और अवसर जहां यह एक समस्या होगी जब स्ट्रिंग किसी फ़ंक्शन से वापसी मान है। चूंकि स्ट्रिंग एक संदर्भ प्रकार है और तकनीकी रूप से शून्य और रिक्त दोनों के रूप में मान हो सकता है, इसलिए फ़ंक्शन तकनीकी रूप से एक शून्य या रिक्त भी लौट सकता है (ऐसा करने से इसे रोकने के लिए कुछ भी नहीं है)। अब, चूंकि "मूल्य के अभाव" की 2 धारणाएं हैं, यानी एक खाली स्ट्रिंग और एक अशक्त, जो सभी फ़ंक्शन इस फ़ंक्शन का उपभोग करते हैं, उन्हें 2 चेक करने होंगे। एक खाली के लिए और दूसरा शून्य के लिए।

संक्षेप में, इसका हमेशा एक राज्य के लिए केवल 1 प्रतिनिधित्व होना अच्छा है। खाली और अशक्त पर एक व्यापक चर्चा के लिए, नीचे दिए गए लिंक देखें।

/software/32578/sql-empty-string-vs-null-value

उपयोगकर्ता इनपुट के साथ काम करते समय रिक्त बनाम खाली


2
और वास्तव में आप इस अंतर को कैसे देखते हैं, एक टेक्स्ट बॉक्स में कहते हैं? क्या उपयोगकर्ता फ़ील्ड में कोई मूल्य दर्ज करना भूल गया है, या वे उद्देश्यपूर्ण रूप से इसे खाली छोड़ रहे हैं? एक प्रोग्रामिंग भाषा में अशक्त का एक विशिष्ट अर्थ है; निर्दिष्ट नहीं किए गए। हम जानते हैं कि इसका कोई मूल्य नहीं है, जो डेटाबेस नल के समान नहीं है।
एंडी

1
जब आप इसे एक पाठ बॉक्स के साथ उपयोग करते हैं तो बहुत अधिक अंतर नहीं होता है। किसी भी तरह से, एक स्ट्रिंग में मूल्य की अनुपस्थिति का प्रतिनिधित्व करने के लिए एक अंकन सर्वोपरि है। अगर मुझे एक चुनना था, तो मैं शून्य चुनूंगा।
नेरवे

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

1
COM (कॉमन ऑब्जेक्ट मॉडल) के तहत जो .net से पहले, एक स्ट्रिंग प्रकार या तो स्ट्रिंग के डेटा के लिए एक पॉइंटर रखेगा, या nullखाली स्ट्रिंग का प्रतिनिधित्व करेगा। कई तरीके हैं। नेट समान शब्दार्थ लागू कर सकते थे, क्या उन्होंने ऐसा करने के लिए चुना था, विशेष रूप से यह दिया गया थाString कई विशेषताएं हैं जो इसे वैसे भी एक अद्वितीय प्रकार बनाती हैं [जैसे कि यह और दो सरणी प्रकार एकमात्र प्रकार हैं जिनके आवंटन आकार स्थिर नहीं है]।
सुपरकैट

7

मूल कारण / समस्या यह है कि CLS विनिर्देशन के डिज़ाइनर (जो परिभाषित करते हैं कि कैसे भाषाएं .net के साथ परस्पर क्रिया करती हैं) ने एक ऐसे साधन को परिभाषित नहीं किया है जिसके द्वारा वर्ग के सदस्य निर्दिष्ट कर सकते हैं कि उन्हें सीधे बुलाया जाना चाहिए, बजायcallvirt कॉल करने के बिना अशक्त-संदर्भ जाँच; न ही यह परिभाषित संरचनाओं का एक माध्यम प्रदान करता है जो "सामान्य" मुक्केबाजी के अधीन नहीं होगा।

सीएलएस विनिर्देश को ऐसे साधनों के रूप में परिभाषित किया गया था, तो यह संभव हो जाएगा। इसके लिए कॉमन ऑब्जेक्ट मॉडल (COM) द्वारा स्थापित लीड का लगातार पालन करें, जिसके तहत एक शून्य स्ट्रिंग संदर्भ को खाली स्ट्रिंग के समान शब्दार्थ माना जाता था, और अन्य के लिए उपयोगकर्ता-परिभाषित अपरिवर्तनीय वर्ग प्रकार जिन्हें डिफ़ॉल्ट मानों को परिभाषित करने के लिए मूल्य शब्दार्थ माना जाता है। अनिवार्य रूप से, प्रत्येक सदस्य के लिए क्या होगा String, जैसे Lengthकुछ लिखा जाना चाहिए [InvokableOnNull()] int String Length { get { if (this==null) return 0; else return _Length;} }। इस दृष्टिकोण ने उन चीजों के लिए बहुत अच्छे शब्दार्थ की पेशकश की है, जिन्हें मूल्यों की तरह व्यवहार करना चाहिए, लेकिन कार्यान्वयन के मुद्दों को ढेर पर संग्रहीत करने की आवश्यकता है। इस दृष्टिकोण के साथ सबसे बड़ी कठिनाई यह है कि ऐसे प्रकारों के बीच रूपांतरण के शब्दार्थ और Objectथोड़ा मुरझाना हो सकता है।

एक वैकल्पिक दृष्टिकोण विशेष संरचना प्रकारों की परिभाषा को अनुमति देने के लिए होता था जो कि विरासत में नहीं मिला था, Objectलेकिन इसके बजाय कस्टम बॉक्सिंग और अनबॉक्सिंग ऑपरेशन थे (जो कि कुछ अन्य प्रकार से / में परिवर्तित हो जाएंगे)। इस तरह के दृष्टिकोण के तहत, एक वर्ग प्रकार होगा NullableStringजो स्ट्रिंग के रूप में व्यवहार करता है, और एक कस्टम-बॉक्सेड संरचना प्रकार String, जो एकल Valueप्रकार का एक निजी क्षेत्र धारण करेगाString । एक कन्वर्ट करने के लिए प्रयास कर रहा है Stringकरने के लिए NullableStringया Objectवापसी होगी Valueयदि गैर-शून्य, या String.Emptyअशक्त है। कास्ट करने की कोशिश कर रहा है String, NullableStringउदाहरण के लिए एक गैर-शून्य संदर्भ में संदर्भ को संग्रहीत किया जाएगा Value(शायद लंबाई शून्य होने पर शून्य को संग्रहीत करना); किसी भी अन्य संदर्भ कास्टिंग एक अपवाद फेंक देंगे।

हालांकि तार को ढेर पर संग्रहीत किया जाना है, फिर भी वैचारिक रूप से कोई कारण नहीं है कि उन्हें क्यों नहीं करना चाहिए मूल्य प्रकार की तरह व्यवहार करना , जिसमें एक गैर-शून्य डिफ़ॉल्ट मान है। उन्हें एक "सामान्य" संरचना के रूप में संग्रहीत किया जाता है, जो एक संदर्भ होता है जो कोड के लिए कुशल होता है जो उन्हें "स्ट्रिंग" के रूप में उपयोग करता है, लेकिन "ऑब्जेक्ट" के लिए कास्टिंग करते समय अप्रत्यक्ष और अक्षमता की एक अतिरिक्त परत जोड़ देगा। हालांकि, मैं इस देर की तारीख में उपरोक्त सुविधाओं में से किसी को भी शामिल नहीं करता हूं। शायद भविष्य के रूपरेखा के डिजाइनर उन पर विचार कर सकते हैं।


1
किसी ऐसे व्यक्ति के रूप में बोलना जो एसक्यूएल में बहुत काम करता है, और ओरेकल के सिरदर्द से निपट गया है, जो NULL और शून्य-लंबाई के बीच अंतर नहीं कर रहा है, मुझे बहुत खुशी है कि .NET करता है । "खाली" एक मूल्य है, "अशक्त" नहीं है।

@JonofAllTrades: मैं असहमत हूं। अनुप्रयोग कोड पर, db कोड से निपटने के अलावा, इसका कोई अर्थ नहीं है कि एक स्ट्रिंग को एक वर्ग के रूप में माना जा रहा है। यह एक मूल्य प्रकार और एक बुनियादी एक है। Supercat: यदि आप करने के लिए +1
फ़ेब्रिकियो अराउजो

1
डेटाबेस कोड एक बड़ा "छोड़कर" है। जब तक कुछ समस्या डोमेन हैं जहां आपको "वर्तमान / ज्ञात, एक खाली स्ट्रिंग" और "वर्तमान / अज्ञात / अनुपयुक्त" जैसे डेटाबेस के बीच अंतर करने की आवश्यकता है, तो भाषा को इसका समर्थन करने की आवश्यकता है। बेशक अब जो .NET है Nullable<>, स्ट्रिंग्स को वैल्यू टाइप के रूप में फिर से लागू किया जा सकता है; मैं इस तरह की पसंद की लागत और लाभ के लिए बात नहीं कर सकता।

3
@JonofAllTrades: कोड जो संख्याओं से संबंधित है, के पास "अपरिभाषित" से डिफ़ॉल्ट मान शून्य को अलग करने का एक आउट-ऑफ-बैंड साधन है। जैसा कि यह है, अशक्त-हैंडलिंग कोड जो स्ट्रिंग्स और संख्याओं के साथ काम करता है, अशक्त स्ट्रिंग्स के लिए एक विधि का उपयोग करना पड़ता है और दूसरा अशक्त संख्याओं के लिए। यहां तक ​​कि अगर एक अशक्त वर्ग प्रकार stringकी तुलना में अधिक कुशल Nullable<string>है, तो "अधिक कुशल" विधि का उपयोग करने के लिए सभी अशक्त डेटा डेटाबेस मूल्यों के लिए एक ही दृष्टिकोण का उपयोग करने में सक्षम होने की तुलना में अधिक बोझ है।
सुपरकैट

5

क्योंकि एक स्ट्रिंग चर एक संदर्भ है , उदाहरण नहीं

डिफ़ॉल्ट रूप से इसे खाली करना संभव है, लेकिन इसने बोर्ड में बहुत सारी विसंगतियां पेश की होंगी।


3
कोई विशेष कारण stringनहीं है कि एक संदर्भ प्रकार होना चाहिए। यह सुनिश्चित करने के लिए, स्ट्रिंग बनाने वाले वास्तविक पात्रों को निश्चित रूप से ढेर पर संग्रहीत किया जाना है, लेकिन सीएलआर में पहले से मौजूद तार को समर्पित समर्थन की मात्रा को देखते हुए, यह System.Stringएक प्रकार के साथ एक मूल्य प्रकार होने के लिए एक खिंचाव नहीं होगा Valueप्रकार का एकल निजी क्षेत्र HeapString। वह फ़ील्ड एक संदर्भ प्रकार होगा, और डिफ़ॉल्ट रूप से होगा null, लेकिन एक Stringसंरचना जिसका Valueफ़ील्ड शून्य था, एक रिक्त स्ट्रिंग के रूप में व्यवहार करेगा। इस दृष्टिकोण का एकमात्र नुकसान होगा ...
सुपरकैट

1
... कि रन-टाइम में विशेष-केस कोड की अनुपस्थिति में, एक Stringकरने के Objectलिए, Stringएक संदर्भ में कॉपी करने के बजाय, ढेर पर एक बॉक्सिंग उदाहरण के निर्माण का कारण बनता है HeapString
सुपरकैट

1
@ सुपरकैट - कोई भी यह नहीं कह रहा है कि स्ट्रिंग का मूल्य प्रकार होना चाहिए।
हेंक होल्टरमैन

1
मेरे सिवा कोई नहीं। स्ट्रिंग होने से एक "विशेष" मान प्रकार (एक निजी संदर्भ-प्रकार के क्षेत्र के साथ) हो सकता है कि अधिकांश हैंडलिंग अनिवार्य रूप से कुशल हो, जैसा कि अब है, विधियों / गुणों .Lengthआदि पर एक जोड़ा अशक्त जांच को छोड़कर, ताकि उदाहरण जो धारण करें एक अशक्त संदर्भ इसे रोकने की कोशिश नहीं करेगा, बल्कि एक खाली स्ट्रिंग के लिए उपयुक्त व्यवहार करेगा। चाहे फ्रेमवर्क बेहतर हो या बुरा stringउस तरह से लागू किया गया हो, अगर default(string)कोई खाली स्ट्रिंग होना चाहता है ...
सुपरकैट

1
... stringसंदर्भ-प्रकार फ़ील्ड पर एक वैल्यू-टाइप रैपर होना एक ऐसा दृष्टिकोण होगा जो कि .net के अन्य भागों में सबसे कम बदलावों की आवश्यकता है। वास्तव में, यदि कोई स्वीकार करने को तैयार है तो अतिरिक्त बॉक्सिंग आइटम बनाने के Stringलिए रूपांतरण होगा। Objectएक बस Stringप्रकार के क्षेत्र के साथ एक साधारण संरचना हो सकती है Char[]जिसे कभी उजागर नहीं किया गया]। मुझे लगता है कि एक HeapStringप्रकार होने से शायद बेहतर होगा, लेकिन कुछ मायनों में मूल्य-प्रकार के स्ट्रिंग को पकड़ना Char[]सरल होगा।
सुपरकैट

5

C # के डिजाइनरों ने स्ट्रिंग के डिफ़ॉल्ट मान के रूप में अशक्त का उपयोग करने के लिए क्यों चुना?

क्योंकि तार संदर्भ प्रकार हैं , संदर्भ प्रकार डिफ़ॉल्ट मान हैंnull । संदर्भ प्रकार के चर वास्तविक डेटा के संदर्भों को संग्रहीत करते हैं।

आइए defaultइस मामले के लिए कीवर्ड का उपयोग करें;

string str = default(string); 

strएक है string, इसलिए यह एक संदर्भ प्रकार है , इसलिए डिफ़ॉल्ट मान है null

int str = (default)(int);

stra है int, इसलिए यह एक मान प्रकार है , इसलिए डिफ़ॉल्ट मान है zero


4

यदि डिफ़ॉल्ट मान stringरिक्त स्ट्रिंग थे, तो मुझे परीक्षण नहीं करना होगा

गलत! डिफ़ॉल्ट मान को बदलना इस तथ्य को नहीं बदलता है कि यह एक संदर्भ प्रकार है और कोई अभी भी स्पष्ट रूप से संदर्भ को सेट कर सकता है null

इसके अतिरिक्त Nullable<String>समझदारी होगी।

सच्ची बात। यह nullकिसी भी प्रकार के संदर्भ के लिए अनुमति देने के लिए अधिक समझ में आता है , इसके बजाय Nullable<TheRefType>उस सुविधा के लिए आवश्यक है।

तो सी # के डिजाइनरों nullने स्ट्रिंग्स के डिफ़ॉल्ट मूल्य के रूप में उपयोग करने का चयन क्यों किया ?

अन्य संदर्भ प्रकारों के साथ संगति। अब, nullसंदर्भ प्रकारों की अनुमति क्यों दें ? शायद इसलिए कि यह सी की तरह महसूस करता है, भले ही यह एक भाषा में एक संदिग्ध डिजाइन निर्णय है जो प्रदान करता है Nullable


3
ऐसा इसलिए हो सकता है क्योंकि Nullable को केवल .NET 2.0 फ्रेमवर्क में पेश किया गया था, इसलिए पहले यह उपलब्ध नहीं था?
jcolebrand

3
धन्यवाद डैन बर्टन ने बताया कि किसी ने प्रारंभिक मूल्य को संदर्भ प्रकारों पर बाद में शून्य करने के लिए निर्धारित किया है। यह सोचने के माध्यम से मुझे बताता है कि प्रश्न में मेरे मूल इरादे का कोई फायदा नहीं है।
मार्सेल

4

शायद अगर आप ??अपने स्ट्रिंग चर को निर्दिष्ट करते समय ऑपरेटर का उपयोग करेंगे , तो यह आपकी मदद कर सकता है।

string str = SomeMethodThatReturnsaString() ?? "";
// if SomeMethodThatReturnsaString() returns a null value, "" is assigned to str.

2

स्ट्रिंग एक अपरिवर्तनीय वस्तु है जिसका अर्थ है जब कोई मूल्य दिया जाता है, तो पुराने मूल्य को मेमोरी से मिटाया नहीं जाता है, लेकिन पुराने स्थान पर रहता है, और नए मूल्य को एक नए स्थान पर रखा जाता है। तो अगर का डिफ़ॉल्ट मान String aथा String.Empty, इसे बर्बाद होगाString.Empty स्मृति में ब्लॉक जब वह अपने पहले मूल्य दिया गया था।

यद्यपि यह घटा हुआ लगता है, यह एक समस्या में बदल सकता है जब डिफ़ॉल्ट मानों के साथ तारों के एक बड़े सरणी को आरंभीकृत करता है String.Empty। बेशक, आप हमेशा उत्परिवर्तित StringBuilderवर्ग का उपयोग कर सकते हैं यदि यह एक समस्या होने जा रही थी।


"पहली आरंभीकरण" बात का उल्लेख करने के लिए धन्यवाद।
मार्सेल

3
किसी बड़े एरे को इनिशियलाइज़ करते समय यह समस्या कैसे होगी? चूंकि, जैसा कि आपने कहा, स्ट्रिंग्स अपरिवर्तनीय हैं, सरणी के सभी तत्व बस उसी के लिए संकेत होंगे String.Empty। क्या मैं गलत हूं?
डैन बर्टन

2
किसी भी प्रकार के लिए डिफ़ॉल्ट मान सभी बिट्स को शून्य पर सेट करने वाला है। stringखाली स्ट्रिंग होने के डिफ़ॉल्ट मान के लिए एकमात्र तरीका खाली स्ट्रिंग के प्रतिनिधित्व के रूप में ऑल-बिट्स-शून्य की अनुमति है। ऐसे कई तरीके हैं, जिन्हें पूरा किया जा सकता है, लेकिन मुझे नहीं लगता कि इसमें कोई संदर्भ शामिल है String.Empty
सुपरकैट

अन्य उत्तरों ने इस बिंदु पर भी चर्चा की। मुझे लगता है कि लोगों ने निष्कर्ष निकाला है कि स्ट्रिंग क्लास को एक विशेष मामले के रूप में मानना ​​और ऑल-बिट्स-शून्य के अलावा कुछ और प्रदान करना नहीं होगा, भले ही यह कुछ ऐसा था String.Emptyया नहीं ""
djv

@ दान: stringभंडारण स्थानों के आरम्भिक व्यवहार को बदलने के लिए उन सभी संरचनाओं या वर्गों के आरंभीकरण व्यवहार को भी बदलना आवश्यक होता है जिनमें प्रकार के क्षेत्र होते हैं string। यह .net के डिजाइन में एक बहुत बड़े बदलाव का प्रतिनिधित्व करता है, जो वर्तमान में किसी भी प्रकार को शून्य-प्रारंभिक करने की अपेक्षा करता है, यहां तक ​​कि यह सोचने के बिना भी कि यह क्या है, केवल इसके कुल आकार के लिए सहेजें।
सुपरकैट

2

चूंकि स्ट्रिंग एक संदर्भ प्रकार है और संदर्भ प्रकार के लिए डिफ़ॉल्ट मान शून्य है।


0

हो सकता है कि stringकीवर्ड ने आपको भ्रमित कर दिया हो, क्योंकि यह बिल्कुल किसी अन्य मूल्य प्रकार की घोषणा की तरह दिखता है , लेकिन यह वास्तव System.Stringमें इस प्रश्न में बताया गया एक उपनाम है ।
इसके अलावा विज़ुअल स्टूडियो में गहरे नीले रंग और निचले अक्षर का पहला अक्षर गलत हो सकता है struct


3
क्या objectकीवर्ड के समान सत्य नहीं है ? हालांकि माना जाता है, कि यह अब तक की तुलना में कम इस्तेमाल किया गया है string

2
के रूप intमें एक उपनाम है System.Int32। अापका नजरिया क्या है? :)
थोरारिन

@Thorari @delnan: वे दोनों उपनाम हो, लेकिन System.Int32एक है Structइस प्रकार एक डिफ़ॉल्ट मान करते हुए System.Stringएक है Classका डिफ़ॉल्ट मान के साथ एक सूचक होने null। वे नेत्रहीन एक ही फ़ॉन्ट / रंग में प्रस्तुत कर रहे हैं। ज्ञान के बिना, कोई सोच सकता है कि वे उसी तरह कार्य करते हैं (= एक डिफ़ॉल्ट मान)। मेरा उत्तर एक en.wikipedia.org/wiki/Cognitive_psychology संज्ञानात्मक मनोविज्ञान विचार के साथ लिखा गया था इसके पीछे :-)
एलेसांद्रो दा रूंगना

मैं काफी हद तक एंडर्स हेजलबर्ग हूं जिसने इसे एक चैनल 9 के साक्षात्कार में कहा था। मैं ढेर और स्टैक के बीच का अंतर जानता हूं, लेकिन सी # के साथ विचार यह है कि आकस्मिक प्रोग्रामर की आवश्यकता नहीं है।
थॉमस कोएले

0

2.0 तक अशक्त प्रकार नहीं आए।

यदि भाषा की शुरुआत में अशक्त प्रकार बनाए गए होते तो स्ट्रिंग नॉन-नॉबल और स्ट्रिंग होती? अशक्त होता। लेकिन वे इस जोड़ी को पिछड़ी अनुकूलता के लिए नहीं कर सके।

बहुत से लोग रेफ-टाइप के बारे में बात करते हैं या रिफ़ टाइप नहीं करते हैं, लेकिन स्ट्रिंग सामान्य वर्ग से बाहर है और समाधान संभव बनाने के लिए पाया गया है।

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