डिफ़ॉल्ट स्ट्रिंग आरंभीकरण: NULL या खाली? [बन्द है]


130

मैंने हमेशा अपने स्ट्रिंग्स को NULL के लिए इनिशियलाइज़ किया है, इस सोच के साथ कि NULL का मतलब मान का अभाव है और "" या String.Empty एक वैल्यू वैल्यू है। मैंने कोड के कुछ और उदाहरण देखे हैं जहाँ String.Empty को डिफ़ॉल्ट मान माना जाता है या कोई मूल्य नहीं दर्शाता है। यह मुझे अजीब लगता है, सी # में नए जोड़े गए अशक्त प्रकारों के साथ ऐसा लगता है जैसे हम 'नो वैल्यू' का प्रतिनिधित्व करने के लिए NULL का उपयोग न करके स्ट्रिंग्स के साथ पीछे की ओर ले जा रहे हैं।

आप डिफॉल्ट इनिशलाइज़र के रूप में क्या उपयोग करते हैं और क्यों?

संपादित करें: उत्तर के आधार पर मैं अपने आगे के विचारों को आगे बढ़ाता हूं

  1. त्रुटि से बचने के लिए यदि मान शून्य होना चाहिए, तो इसे NULLपहली जगह पर सेट क्यों किया गया ? शायद उस जगह पर त्रुटि को पहचानना बेहतर होगा जहां यह आपके बाकी कोडबेस के माध्यम से इसे कवर करने के बजाय होता है?

  2. अशक्त जाँच से बचना यदि आप कोड में अशक्त जाँच करते-करते थक गए हैं, तो क्या यह अशक्त जाँच को रोकना बेहतर नहीं होगा? शायद स्ट्रिंग (या विस्तार!) उन्हें NULLसुरक्षित बनाने के लिए स्ट्रिंग तरीके ? यदि आप लगातार उपयोग करते हैं String.Emptyऔर एक अशक्त होता है तो यह आपके सिस्टम में काम करने के लिए होता है, क्या आप जोड़ना शुरू करते हैंNULL भी तरह से चेक ?

मैं मदद नहीं कर सकता लेकिन इस राय पर लौट आया कि यह आलस्य है। यदि आप nullउसके डेटाबेस में इसके बजाय '' का प्रयोग करते हैं, तो कोई भी DBA आपको मूर्खतापूर्ण तरीके से नौ थप्पड़ मारेगा । मुझे लगता है कि प्रोग्रामिंग में समान सिद्धांत लागू होते हैं और सिर को उल्टा करने के लिए कोई ऐसा व्यक्ति होना चाहिए जो String.Emptyइसके बजाय उपयोग करता होNULL बिना मूल्य का प्रतिनिधित्व करने के करता हो।

संबंधित सवाल


'द साने'? मुझे पता है कि एक दाना नहीं होना चाहिए।
vfilby

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

मुझे पता है, लेकिन कभी-कभी यह नाटक करने का मज़ा है अन्यथा।
द साने

1
मैं एमवीसी फॉर्म संग्रह या सत्र चर पर इस समस्या में भाग लेता हूं, मैंने पाया कि सबसे उपयोगी बात यह थी कि अशक्त को स्ट्रिंग में परिवर्तित कर दिया जाए। इसके साथ खाली करें ?? आशुलिपि, और फिर जो भी स्ट्रिंग ऑपरेशन की आवश्यकता होती है उसे लागू करें। जैसे। (आइटम ?? स्ट्रिंग। इम्प्टी) ।ट्रीम ()। टॉपर ()
सोनजज

4
यह रचनात्मक नहीं है ??
नवफाल

जवाबों:


111

"खाली" और NULL के बीच अंतर करने के लिए +1। मैं इस बात से सहमत हूं कि "खाली" का अर्थ "वैध, लेकिन रिक्त" और "रिक्त" का अर्थ "अमान्य" होना चाहिए।

तो मैं इस तरह आपके सवाल का जवाब दूंगा:

खाली जब मैं एक मान्य सामान्य मूल्य कि या परिवर्तित नहीं हो सकता है, उदाहरण के लिए, यदि कोई उपयोगकर्ता मध्य नाम है चाहता हूँ।

NULL जब यह एक त्रुटि है यदि आगामी कोड मान को स्पष्ट रूप से सेट नहीं करता है।


11
जब वास्तव में दोनों के बीच अंतर होता है तो NULL और खाली के बीच अंतर करना बहुत अच्छा होता है। हालांकि, कई मामले हैं, जहां कोई अंतर नहीं है, और इस तरह एक ही चीज का प्रतिनिधित्व करने के दो तरीके हैं, एक दायित्व है।
ग्रेग स्माल्टर

6
@Greg: जबकि मैं मानता हूं कि विविधता में भ्रम की संभावना है, यह एक बड़ी संपत्ति भी हो सकती है। वैध और अमान्य मानों के बीच अंतर करने के लिए "" या पूर्ण लिखने का सरल, सुसंगत सम्मेलन आपके कोड को समझने में आसान बना देगा। यही कारण है कि मैं हमेशा "यदि (var)," संकेत के साथ "if (var! = NULL)" और पूर्णांक के साथ "if (var! = 0)" का परीक्षण करता हूं - तो इन सभी का मतलब कंपाइलर से समान होता है! लेकिन वे अतिरिक्त जानकारी रखते हैं जो गरीब डेवलपर की मदद करता है जो मेरे कोड को बनाए रखता है।
एडम लिस

32

MSDN के अनुसार :

के Emptyबजाय मूल्य के साथ तार इनिशियलाइज़ करके null, आप एक NullReferenceExceptionहोने की संभावना को कम कर सकते हैं ।

हमेशा उपयोग IsNullOrEmpty()करना अच्छा अभ्यास है।


45
सिर्फ इसलिए कि आप अपवाद की संभावना को कम कर रहे हैं इसका मतलब यह नहीं है कि अपवाद नहीं होना चाहिए। यदि आपका कोड वहां होने वाले मूल्य पर निर्भर करता है, तो उसे एक अपवाद फेंक देना चाहिए!
rmeador

1
यकीन है, वहाँ कोई तर्क नहीं। OTOH, यदि आप केवल एक साथ तार जोड़ रहे हैं ... मुझे लगता है कि यह कोडिंग शैली, अनुभव और स्थिति पर निर्भर करता है।
तोमलक

यह मुख्य रूप से है जो मैं अंतर का उपयोग करता हूं जो भी उपयोग करना है।
पॉजिटिव

3
मत भूलना IsNullOrWhiteSpace () नेट ढांचे के लिए 4
Coops

13

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

मैं इसे बहुत देखता हूं:

string name = null; // or String.Empty
if (condition)
{
  name = "foo";
}
else
{
  name = "bar";
}

return name;

अशक्त करने के लिए प्रारंभिक रूप से प्रभावी नहीं होगा। इसके अलावा, सबसे अधिक बार आप एक मूल्य सौंपा जाना चाहते हैं। अशक्त करने के लिए, आप संभावित रूप से कोड पथ को याद कर सकते हैं जो मान प्रदान नहीं करते हैं। इस तरह:

string name = null; // or String.Empty
if (condition)
{
  name = "foo";
}
else if (othercondition)
{
  name = "bar";
}

return name; //returns null when condition and othercondition are false

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

माथिजिस


विज़ुअल स्टूडियो में, जो मेरा मानना ​​है कि लगभग हर C # प्रोग्रामर उपयोग करता है, आपकी दूसरी स्थिति (बिना = null) एक चेतावनी उत्पन्न करती है, ठीक उसी कारण से जिसके लिए आपने कहा था - इससे कोई फर्क नहीं पड़ता कि स्ट्रिंग का डिफ़ॉल्ट मान शून्य है। यदि आप हर कोड पथ के माध्यम से असाइनमेंट की गारंटी नहीं देते हैं, तो IDE (और / या मैं अंतर्निहित कंपाइलर [?] मान लीजिए) एक चेतावनी उत्पन्न करेगा। हालांकि चेतावनियाँ संकलन को नहीं रोकेंगी, फिर भी वे वहाँ हैं - जिन्हें आसानी से हल किया जा सकता है, वे दूसरों को बाधित करने में मदद कर सकते हैं जो प्रोग्रामर का ध्यान आकर्षित कर सकते हैं
कोड जॉकी

मेरी जानकारी के लिए, पहले इस स्थिति का आरंभीकरण के बिना पूरी तरह से खुश हो जाएगा nameकरने के लिए null, (कोई चेतावनी) क्योंकि हर कोड पथ के लिए एक मूल्य प्रदान करती है name- सब पर वहाँ प्रारंभ करने की कोई जरूरत नहीं
कोड जॉकी

8

अधिकांश सॉफ़्टवेयर के लिए जो वास्तव में स्ट्रिंग-प्रोसेसिंग सॉफ़्टवेयर नहीं है, प्रोग्राम लॉजिक को स्ट्रिंग चर की सामग्री पर निर्भर नहीं होना चाहिए। जब भी मैं एक कार्यक्रम में ऐसा कुछ देखता हूं:

if (s == "value")

मुझे बुरा लग रहा है। इस पद्धति में एक स्ट्रिंग शाब्दिक क्यों है? सेटिंग क्या है s? क्या यह पता है कि तर्क स्ट्रिंग के मूल्य पर निर्भर करता है? क्या यह पता है कि इसे काम करने के लिए निचला मामला होना चाहिए? क्या मुझे इसे उपयोग करने के लिए बदलकर इसे ठीक करना चाहिए String.Compare? क्या मुझे इसमें एक Enumऔर पार्सिंग बनाना चाहिए ?

इस दृष्टिकोण से, किसी को कोड का एक दर्शन मिलता है जो बहुत सरल है: आप जहां भी संभव हो एक स्ट्रिंग की सामग्री की जांच करने से बचते हैं। एक स्ट्रिंग की तुलना String.Emptyकरना वास्तव में सिर्फ एक शाब्दिक से तुलना करने का एक विशेष मामला है: यह कुछ ऐसा करने से बचने के लिए है जब तक आपको वास्तव में नहीं करना है।

यह जानने के बाद, जब मैं अपने कोड आधार में कुछ इस तरह देखता हूं तो मैं पलक नहीं झपकाता:

string msg = Validate(item);
if (msg != null)
{
   DisplayErrorMessage(msg);
   return;
}

मुझे पता है कि Validateवह कभी नहीं लौटेगा String.Empty, क्योंकि हम इससे बेहतर कोड लिखते हैं।

बेशक, बाकी दुनिया इस तरह से काम नहीं करती है। जब आपका प्रोग्राम उपयोगकर्ता इनपुट, डेटाबेस, फाइलें, और इसी तरह से काम कर रहा है, तो आपको अन्य दर्शन के लिए ध्यान देना होगा। वहां, अराजकता पर आदेश थोपना आपके कोड का काम है। उस आदेश का एक हिस्सा यह जान रहा है कि खाली स्ट्रिंग का मतलब String.Emptyकब होना चाहिए और इसका मतलब कब होना चाहिए null

(बस यह सुनिश्चित करने के लिए कि मैं अपनी गांड से बात नहीं कर रहा था, मैंने अभी-अभी .I String.IsNullOrEmpty ’के लिए अपना कोडबेस खोजा है। इसके सभी ५४ घटनाएं ऐसे तरीकों में हैं, जो उपयोगकर्ता इनपुट की प्रक्रिया करते हैं, पायथन स्क्रिप्ट से मान लौटाते हैं, प्राप्त मानों की जाँच करते हैं। बाहरी एपीआई, आदि)


6

यह वास्तव में सी # भाषा में एक अंतराल छेद है। एक स्ट्रिंग को परिभाषित करने का कोई तरीका नहीं है जो शून्य नहीं हो सकता है। यह उन समस्याओं के रूप में सरल होता है, जिनका आप वर्णन कर रहे हैं, जो प्रोग्रामर को एक ऐसा निर्णय लेने के लिए मजबूर करती हैं, जो उन्हें नहीं करना चाहिए, क्योंकि कई मामलों में NULL और String.Empty का एक ही मतलब है। बदले में, बाद में अन्य प्रोग्रामर्स को NULL और String.Empty दोनों को संभालने के लिए मजबूर कर सकता है, जो कि कष्टप्रद है।

एक बड़ी समस्या यह है कि डेटाबेस आपको उन क्षेत्रों को परिभाषित करने की अनुमति देता है जो नक्शे को C # स्ट्रिंग में परिभाषित करते हैं, लेकिन डेटाबेस फ़ील्ड को NOT NULL के रूप में परिभाषित किया जा सकता है। इसलिए, C # प्रकार का उपयोग करके SQL सर्वर में एक varchar (100) NOT NULL फ़ील्ड को सही ढंग से दर्शाने का कोई तरीका नहीं है।

अन्य भाषाएँ, जैसे कि Spec #, इसे अनुमति देते हैं।

मेरी राय में, एक स्ट्रिंग को परिभाषित करने में C # की अक्षमता है जो अशक्त करने की अनुमति नहीं देता है यह एक पूर्व को परिभाषित करने में असमर्थता के रूप में उतना ही बुरा है कि एक अशक्त को परिभाषित करने की अनुमति नहीं देता है।

आपके प्रश्न का पूरी तरह से उत्तर देने के लिए: मैं हमेशा डिफ़ॉल्ट आरंभीकरण के लिए खाली स्ट्रिंग का उपयोग करता हूं क्योंकि यह डेटाबेस डेटा प्रकारों के काम करने के तरीके के समान है। (संपादित करें: यह कथन बहुत अस्पष्ट था। इसे पढ़ना चाहिए "मैं डिफ़ॉल्ट इनिशियलाइज़ेशन के लिए खाली स्ट्रिंग का उपयोग करता हूं जब NULL एक शानदार स्थिति है, उसी तरह मैंने एक डेटाबेस कॉलम सेट किया है यदि NULL नहीं है, तो NULL एक अति-विशिष्ट स्थिति होगी। इसी तरह। मेरे कई DB कॉलम नॉट NULL के रूप में सेट किए गए हैं, इसलिए जब मैं उन लोगों को C # स्ट्रिंग में लाऊंगा, तो स्ट्रिंग खाली हो जाएगी या उनका मूल्य होगा, लेकिन कभी भी NULL नहीं होगा। दूसरे शब्दों में, मैं केवल NULL को एक स्ट्रिंग इनिशियलाइज़ करता हूँ। अगर null का एक अर्थ है जो String.Empty के अर्थ से अलग है, और मुझे लगता है कि मामला सामान्य से कम है (लेकिन यहां लोगों ने इस मामले के वैध उदाहरण दिए हैं)। ")


String.Empty का उपयोग करना केवल उन तरीकों में से एक के समान है जो डेटाबेस स्ट्रिंग को परिभाषित करता है। बिना किसी मूल्य का प्रतिनिधित्व करने के लिए अशक्त का उपयोग करना अशक्त नवरचार के साथ बहुत अधिक अनुरूप है। मुझे लगता है कि उनके नमक के लायक कोई भी डीबीए आपको मूर्खतापूर्ण तरीके से नौ तरीकों से थप्पड़ मारता है यदि आपने बिना मूल्य का प्रतिनिधित्व करने के लिए '' का इस्तेमाल किया है।
vfilby

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

आप ठीक कह रहे हैं, मेरा आखिरी दावा पर्याप्त स्पष्ट नहीं था। ज्यादातर बार, मेरे डेटाबेस कॉलम NULL नहीं होते हैं (क्योंकि खाली स्ट्रिंग और NULL का अर्थ कोई अंतर नहीं होगा), इसलिए मैं अपने तारों को समान रखने की कोशिश करता हूं ताकि उनमें कभी अशक्त न हो, और यही मेरा मतलब है।
ग्रेग स्माल्टर

5

निर्भर करता है।

क्या आपको यह बताने में सक्षम होने की आवश्यकता है कि क्या मूल्य गायब है (क्या इसे परिभाषित नहीं किया जाना संभव है)?

क्या खाली स्ट्रिंग उस स्ट्रिंग के उपयोग के लिए एक वैध मूल्य है?

यदि आपने दोनों के लिए "हां" उत्तर दिया है, तो आप अशक्त उपयोग करना चाहते हैं। अन्यथा आप "कोई मूल्य नहीं" और "खाली स्ट्रिंग" के बीच अंतर नहीं बता सकते।

यदि आपको यह जानने की आवश्यकता नहीं है कि क्या कोई मूल्य नहीं है, तो खाली स्ट्रिंग शायद अधिक सुरक्षित है, क्योंकि यह आपको जहाँ भी आप उपयोग करते हैं, अशक्त चेक को छोड़ने की अनुमति देता है।



3

मैं या तो इसे "" या अशक्त पर सेट करता हूं - मैं हमेशा String.IsNullOrEmpty का उपयोग करके जांच करता हूं, इसलिए या तो ठीक है।

लेकिन मेरे अंदर का गीक कहता है कि मैं इसे इसके लिए उचित मूल्य होने से पहले इसे शून्य पर सेट करना चाहिए ...



2

क्या यह संभव है कि यह एक त्रुटि परिहार तकनीक है (सलाह योग्य है या नहीं ..)? चूंकि "" अभी भी एक स्ट्रिंग है, आप उस पर स्ट्रिंग फ़ंक्शन कॉल करने में सक्षम होंगे जो कि एक अपवाद के परिणामस्वरूप होता है अगर यह NULL था?


1
यह वह बहाना है जो मैं आमतौर पर सुनता हूं, सिर्फ आलस्य की तरह लगता है। "मैं इस मूल्य को जांचना नहीं चाहता हूं इसलिए मैं शॉर्टकट लेने जा रहा हूं" यह मुझे कैसा लगता है।
vfilby

हाँ, मैं असहमत नहीं हूँ। कुछ परिस्थितियाँ हो सकती हैं जहाँ त्रुटि जाँच कोड की मात्रा को कम करना अच्छा है, लेकिन फ़ंक्शन कॉल का कोई प्रभाव नहीं है या तो सबसे बड़ा नहीं है ..
दाना साने

2

मैं हमेशा उन्हें इनिशियलाइज़ करता हूं NULL

मैं हमेशाstring.IsNullOrEmpty(someString) यह मान रखने के लिए उपयोग करता हूं ।

सरल।


1

यह स्थिति पर निर्भर करता है। ज्यादातर मामलों में मैं String.Empty का उपयोग करता हूं क्योंकि मैं हर बार जब मैं स्ट्रिंग का उपयोग करने का प्रयास करता हूं तो मैं अशक्त जांच नहीं करना चाहता हूं। यह कोड को बहुत सरल बनाता है और आपको अवांछित NullReferenceException क्रैश की शुरुआत करने की संभावना कम होती है।

मैं केवल स्ट्रिंग को अशक्त करने के लिए सेट करता हूं जब मुझे यह जानने की आवश्यकता होती है कि क्या इसे सेट किया गया है या नहीं और जहां एक खाली स्ट्रिंग इसे सेट करने के लिए कुछ मान्य है। व्यवहार में, मुझे ये स्थितियाँ दुर्लभ लगती हैं।


1

एक रिक्त स्ट्रिंग एक मान है (पाठ का एक टुकड़ा, जो संयोगवश, किसी भी पत्र को शामिल नहीं करने के लिए होता है)। अशक्त का कोई मूल्य नहीं है।

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


1

टोमलाक प्रतिक्रिया को दोहराते हुए, ध्यान रखें कि जब आप स्ट्रिंग चर को शून्य के प्रारंभिक मूल्य पर असाइन करते हैं, तो आपका चर अब एक स्ट्रिंग ऑब्जेक्ट नहीं है; C # में किसी भी वस्तु के साथ समान। इसलिए, यदि आप अपने चर के लिए किसी भी तरीके या गुणों का उपयोग करने का प्रयास करते हैं और आप मान रहे हैं कि यह एक स्ट्रिंग ऑब्जेक्ट है, तो आपको NullReferenceException अपवाद मिलेगा।


1

नल का उपयोग केवल उन मामलों में किया जाना चाहिए जहां एक मूल्य वैकल्पिक है। यदि मान वैकल्पिक नहीं है (जैसे 'नाम' या 'पता'), तो मान कभी भी शून्य नहीं होना चाहिए। यह डेटाबेस के साथ-साथ POCO और यूजर इंटरफेस पर भी लागू होता है। नल का अर्थ है "यह मूल्य वैकल्पिक है, और वर्तमान में अनुपस्थित है।"

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

व्यक्तिगत रूप से मैं इसके बजाय डिफ़ॉल्ट रूप से अशक्त नहीं होना चाहूंगा, लेकिन इसके बजाय यदि हम "स्ट्रिंग" घोषित करते हैं तो केवल अशक्त होगा। हालांकि शायद यह गहरे स्तर पर संभव या तार्किक नहीं है; निश्चित नहीं।



0

मुझे लगता है कि बिना कारण (या इस स्थान पर प्रोग्राम फ्लो में नहीं) मूल्य के लिए अशक्त का उपयोग नहीं करने का कोई कारण नहीं है। यदि आप भेद करना चाहते हैं, तो == अशक्त है। यदि आप बस एक निश्चित मूल्य की जांच करना चाहते हैं और परवाह नहीं करते हैं कि यह अशक्त है या कुछ अलग है, String.Equals ("XXX", MyStringVar) ठीक करता है।

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