एक संभवतः अशक्त वस्तु के लिए ToString कैसे करें?


97

निम्नलिखित करने का एक सरल तरीका है:

String s = myObj == null ? "" : myObj.ToString();

मुझे पता है कि मैं निम्नलिखित कर सकता हूं, लेकिन मैं वास्तव में इसे हैक के रूप में मानता हूं:

String s = "" + myObj;

यह बहुत अच्छा होगा यदि Convert.ToString () के पास इसके लिए उचित अधिभार है।


3
मैं पहले वाले के साथ कुछ भी गलत नहीं देखता। यदि आप दूसरे को हैक मानते हैं, तो आप सबसे अच्छा शर्त केवल एक उपयोगिता फ़ंक्शन लिखना है जो अशक्त जांच करता है।
निक लार्सन

plz आप अपने प्रश्न के बारे में अधिक सटीक हो सकते हैं
फोस्टरजेड

3
string.Format ("{0}", myObj) शून्य मानों को स्वीकार करता है।
होलस्टेब्रो

3
C # 6.0 के साथ अब हम null-conditional ऑपरेटर्स का उपयोग कर सकते हैं, जैसे theText? .TString () (.Text? .Trim ()
संतोष

2
इस उत्तर के अनुसार Convert.ToString()सबसे पहले आपके द्वारा लिखी गई पहली बात है।
18

जवाबों:


175

C # 6.0 संपादित करें:

C # 6.0 के साथ अब हमारे पास ओरिजिनल विधि का एक संक्षिप्त, कास्ट-फ्री संस्करण हो सकता है:

string s = myObj?.ToString() ?? "";

या यहां तक ​​कि प्रक्षेप का उपयोग करते हुए:

string s = $"{myObj}";

मूल उत्तर:

String s = (myObj ?? String.Empty).ToString();

या

String s = (myObjc ?? "").ToString()

और भी संक्षिप्त होना।

दुर्भाग्य से, जैसा कि बताया गया है कि गैर-स्ट्रिंग या ऑब्जेक्ट प्रकारों के साथ इस काम को करने के लिए आपको अक्सर दोनों तरफ कलाकारों की आवश्यकता होगी:

String s = (myObjc ?? (Object)"").ToString()
String s = ((Object)myObjc ?? "").ToString()

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

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

public static string ToStringNullSafe(this object value)
{
    return (value ?? string.Empty).ToString();
}

क्या यह संकलन करेगा? क्या तालमेल ऑपरेटर प्रकार की जाँच नहीं करता है?
निक लार्सन

1
यह तब से काम करता है (ऑब्जेक्ट ?? स्ट्रिंग) रिटर्न ऑब्जेक्ट, क्योंकि कोलेस कम से कम सामान्य प्रकार का उपयोग करता है। लेकिन मुझे लगता है कि यह अभ्यस्त इंटरफेस के लिए काम करता है क्योंकि यह तय नहीं कर सकता कि किस इंटरफ़ेस को चुना गया है (क्योंकि प्रत्येक वर्ग के लिए कई इंटरफेस की अनुमति है)।
कोडिमैनिक्स

1
नहीं वास्तव में मैं जिस समाधान की उम्मीद कर रहा था, लेकिन मैं इसे स्वीकार करूंगा
कोडमाइनिक्स

4
डाउनवोटिंग उस ऑब्जेक्ट कास्ट के रूप में बहुत बदसूरत है और इसमें बॉक्सिंग शामिल है।
स्टीफन

1
सी # 6 का पहला विकल्प बहुत ही सुंदर है
एलेक्जेंडर एन।

40
string.Format("{0}", myObj);

string.Format एक रिक्त स्ट्रिंग के रूप में नल को प्रारूपित करेगा और गैर-अशक्त वस्तुओं पर ToString () कॉल करेगा। जैसा कि मैं इसे समझता हूं, यह वही है जो आप ढूंढ रहे थे।


3
मैं व्यक्तिगत रूप से इस तरह नहीं है। यह कोड स्ट्रिंग स्ट्रिंग = myObj == null की तुलना में बहुत कम हो सकता है? "": myObj.ToString (), लेकिन आप अपने तरीके के पीछे तर्क को पूरी तरह से छिपाते हैं।
AGuyCalledGerald

माना जाता है कि यह माइक्रोपोटीमाइजेशन है, लेकिन इसमें सिर्फ 5 गुना ज्यादा समय लगता है "" + myObj। लेकिन मैंने पढ़ा है कि अतिरिक्त तार बनाता है। str.Concat(myObj)बस ठीक काम करने लगता है और "और भी तेज" है।
drzaus

18

यह बहुत अच्छा होगा यदि Convert.ToString () के पास इसके लिए उचित अधिभार है।

वहाँ एक Convert.ToString(Object value).Net 2.0 (लगभग 5 साल पहले इस प्रश्न के बाद पूछा गया था), जो वास्तव में आप चाहते हैं करने के लिए प्रकट होता है:

http://msdn.microsoft.com/en-us/library/astxcyeh(v=vs.80).aspx

क्या मुझे याद आ रहा है / यहाँ कुछ गलत हो रहा है?


1
तुम नहीं, वे करते हैं। सरल क्यों है जब यह जटिल हो सकता है :)
alex.peter

13

एक विस्तार विधि के साथ, आप इसे पूरा कर सकते हैं:

public static class Extension
{
    public static string ToStringOrEmpty(this Object value)
    {
        return value == null ? "" : value.ToString();
    }
}

निम्नलिखित स्क्रीन के लिए कुछ भी नहीं लिखेंगे और एक अपवाद नहीं फेंकेंगे:

        string value = null;

        Console.WriteLine(value.ToStringOrEmpty());

क्या विस्तार विधि कॉल नल्स के लिए सामान्य जांच को छोड़ देती है ...?
मैटी विर्ककुनेन

2
यह जोड़ता है कि आपको "{0}" टाइप नहीं करना है और आप एक विधि नाम चुन सकते हैं जो बताता है कि आप क्या कर रहे हैं। यह विशेष रूप से तब उपयोगी होता है जब आप कई बार ऐसा कर रहे होते हैं। तुम भी विधि ToStringOrEmptyWhenNull नाम दे सकते हैं।
पीटर वैन जिन्केल

2
यदि ओपी सोचता है कि string s = "" + myObj;हैकिश है, तो एक अशक्त वस्तु पर एक फ़ंक्शन कॉल करना उसी नाव में गिरना चाहिए। मैं इसे कम कर दूंगा, लेकिन यह समस्या को हल करता है, मैं इसके उपयोग से असहमत हूं। अशक्त वस्तुओं को NullReferenceExceptionविस्तार विधियों में भी फेंकना चाहिए ।
निक लार्सन

2
@NickLarsen: मैं ज्यादातर मौकों पर आपसे सहमत हूं, लेकिन कभी-कभी आप केवल एक सरल विधि कॉल की सुविधा चाहते हैं। विधि का नाम आपको संकेत देना चाहिए कि अशक्त संदर्भ ठीक हैं, जैसे प्रस्ताव के लिए ToStringOrEmptyWhenNull
जोर्डो

3
एक्सटेंशन विधियाँ तब नहीं फेंकती हैं जब "पहले" पैरामीटर ( thisपैरामीटर) क्योंकि वे केवल वाक्यविन्यास चीनी होते हैं। यही कारण है x.SomeExtensionMethod()के लिए वाक्यात्मक चीनी है SomeStaticClass.SomeExtensionMethod(x);इस प्रकार, जब xहै nullकि हम एक पर एक विधि को लागू करने की प्रयास नहीं करता है nullवस्तु बल्कि एक गुजर nullएक स्थिर विधि करने के लिए वस्तु। यदि और केवल अगर यह विधि एक nullपैरामीटर के लिए जांच करती है और जब एक nullवस्तु फेंक पर "एक्सटेंशन" का विस्तार किया जाता है तो ऐसी मुठभेड़ का सामना करना पड़ेगा ।
जेसन

7

मैं इससे सहमत नहीं हूं:

String s = myObj == null ? "" : myObj.ToString();

किसी भी तरह से एक हैक है। मुझे लगता है कि यह स्पष्ट कोड का एक अच्छा उदाहरण है। यह बिल्कुल स्पष्ट है कि आप क्या हासिल करना चाहते हैं और आप अशक्त होने की उम्मीद कर रहे हैं।

अपडेट करें:

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


उन्होंने यह नहीं कहा कि यह तरीका हैक था। वास्तव में उन्होंने यह नहीं कहा कि इसके साथ क्या गलत था, शायद यह सिवाय इसके कि यह सरल नहीं था। मुझे नहीं लगता कि इस पद्धति में कुछ भी गलत है। +1 क्योंकि मैं इसे इस तरह से करूंगा।
मार्क बायर्स

मैं ओपी से सहमत हूं ... सी # में पहले से ही एक अशक्त सहकर्मी ऑपरेटर है - नीचे मेरी पोस्ट देखें।
एंड्रयू हैलन

मुझे लगता है कि इस मामले में अशक्त coalescing संचालक थोड़ा कम स्पष्ट है, हालांकि मैं इसका उपयोग करने के साथ ठीक होगा।
स्टीफन

@ पीटर मेला काफी। लेकिन यह करता है। सवाल यह है कि "क्या निम्नलिखित करने का एक सरल तरीका है: ..."। यह सटीक तरीका सरल है!
स्टेपिनार

मैंने कभी नहीं कहा, कि यह तरीका हैक है। कृपया मेरे सवाल को फिर से पढ़ें। मुझे केवल फ्रेमवर्क में थोड़ा फ़ंक्शन याद है जिसमें यह कार्यक्षमता है।
कोडमाइनिक्स

4
string s = String.Concat(myObj);

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


2
यह "" + myObj का स्पष्ट रूप है, लेकिन यह बताने में और भी बुरा है कि यहां क्या हो रहा है। वैसे भी दिलचस्प है।
कोडीनिक्स

@codymanix मुझे नहीं लगता कि यह एक ही है - Concatवास्तव में एक शून्य की जांच करता है और रिटर्न देता है string.Emptyया arg0.ToString(), जो थोड़ा अधिक प्रदर्शन करने वाला लगता है (मेरा मतलब है, हम यहां एमएस की बात कर रहे हैं)।
ड्रूज़

2

वास्तव में मुझे समझ में नहीं आया कि आप क्या करना चाहते हैं। जैसा कि मैं समझता हूं, आप इस कोड को इस तरह से लिख सकते हैं। आप यह पूछ रहे हैं या नहीं? क्या आप और अधिक व्याख्या कर सकते हैं?

string s = string.Empty;
    if(!string.IsNullOrEmpty(myObj))
    {
    s = myObj.ToString();
    }

यकीन है कि मैं इसे इस तरह लिख सकता हूं, लेकिन मुझे एक छोटा सा फंक्शन कॉल चाहिए, मैं सोच रहा था कि .NET BCL में ऐसा कुछ क्यों नहीं है
कोडिमैनिक्स

क्या आपको वास्तव में IsNullOrEmpty () विधि होने पर एक फ़ंक्शन की आवश्यकता है?
सेरकन हेकिमोग्लू

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

1
string s = string.IsNullOrEmpty(myObj) ? string.Empty : myObj.ToString();
निक लार्सन

2

मुझे अपने उत्तर के लिए मार पड़ सकती है लेकिन यहाँ वैसे भी जाता है:

मैं बस लिखूंगा

string s = "" if (myObj! = null) {x = myObj.toString (); }

क्या टर्नरी ऑपरेटर के उपयोग के लिए प्रदर्शन के मामले में कोई भुगतान है? मैं अपने सिर के ऊपर से नहीं जानता।

और स्पष्ट रूप से, जैसा कि ऊपर उल्लेख किया गया है, आप इस व्यवहार को एक विधि में रख सकते हैं जैसे कि सेफस्ट्रिंग (myObj) जो पुन: उपयोग की अनुमति देता है।


OMG यदि ऑब्जेक्ट अशक्त है तो उस पर ToString () कॉल करें?
कोडमाइनिक्स

चलो, वह टाइपो है। मैंने पहले = को बदल दिया है! इसे सही करने के लिए। लेकिन आप वास्तव में -1 टाइपो के लिए जा रहे हैं?
जायदेल

2

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

string myStr = (string)myObj; // string in a object disguise or a null

सबसे छोटा और सबसे अच्छा समाधान। (Obj1 ?? "") .ToString () वास्तव में पहली बार Obj1 स्ट्रिंग के रूप में भी :)
TPAKTOPA

2

कुछ (गति) प्रदर्शन परीक्षण विभिन्न विकल्पों का सारांश देते हैं, ऐसा नहीं है कि यह वास्तव में #microoptimization (एक लाइनपैड विकल्प का उपयोग करके ) मायने रखता है

विकल्प

void Main()
{
    object objValue = null;
    test(objValue);
    string strValue = null;
    test(strValue);
}

// Define other methods and classes here
void test(string value) {
    new Perf<string> {
        { "coallesce", n => (value ?? string.Empty).ToString() },
        { "nullcheck", n => value == null ? string.Empty : value.ToString() },
        { "str.Format", n => string.Format("{0}", value) },
        { "str.Concat", n => string.Concat(value) },
        { "string +", n => "" + value },
        { "Convert", n => Convert.ToString(value) },
    }.Vs();
}

void test(object value) {
    new Perf<string> {
        { "coallesce", n => (value ?? string.Empty).ToString() },
        { "nullcheck", n => value == null ? string.Empty : value.ToString() },
        { "str.Format", n => string.Format("{0}", value) },
        { "str.Concat", n => string.Concat(value) },
        { "string +", n => "" + value },
        { "Convert", n => Convert.ToString(value) },
    }.Vs();
}

संभवतः यह इंगित करने के लिए महत्वपूर्ण है कि Convert.ToString(...)एक अशक्त स्ट्रिंग को बनाए रखेगा।

परिणाम

वस्तु

  • nullcheck 1.00x 1221 टिके हुए (0.1221 ms) समाप्त हो गए [10K प्रतिनिधि में, 1.221E-05 एमएस प्रति]।
  • coallesce 1.14x 1387 टिके हुए (0.1387 एमएस) [10K प्रतिनिधि में, 1.387E-05 एमएस प्रति]।
  • स्ट्रिंग + 1.16x 1415 टिके हुए (0.1415 एमएस) [10K प्रतिनिधि में, 1.415E-05 एमएस]]
  • str.Concat 1.16x 1420 टिके हुए (0.142 एमएस) [10K प्रतिनिधि में, 1.42E-05 एमएस प्रति]।
  • १.५ Convertx १ ९ ३१ टिके हुए बीमित (०.१ ९ ३१ एमएस) में परिवर्तित करें [१० के प्रतिनिधि में १.९ ३१ ई-०५ एमएस]
  • str.Format 5.45x 6655 टिके हुए (0.6655 एमएस) [10K प्रतिनिधि में, 6.655E-05 एमएस प्रति]।

तार

  • nullcheck 1.00x 1190 टिके हुए (0.119 ms) समाप्त हो गए [10K प्रतिनिधि में, 1.19E-053 प्रति]।
  • परिवर्तित करें 1.01x 1200 टिक बीता हुआ (0.12 एमएस) [10K प्रतिनिधि में, 1.2E-05 एमएस प्रति]।
  • स्ट्रिंग + १.०४x १२३ ९ टिकियाँ समाप्त (०.१२३ ९ एमएस) [१० के प्रतिनिधि में, १.२३ ९ई-०५१ प्रति टन]
  • coallesce 1.20x 1423 टिके हुए (0.1423 एमएस) [10K प्रतिनिधि में, 1.423E-05 एमएस प्रति]।
  • str.Concat 4.57x 5444 टिक के साथ (0.5444 एमएस) [10K प्रतिनिधि में, 5.444E-05 एमएस प्रति]।
  • str.Format 5.67x 6750 टिके हुए (0.675 एमएस) [10K प्रतिनिधि में, 6.75E-058 प्रति]।

1

Holstebroe की टिप्पणी आपका सबसे अच्छा जवाब होगा:

string s = string.Format("{0}", myObj);

अगर myObj अशक्त है, तो प्रारूप वहां एक रिक्त स्ट्रिंग मान रखता है।

यह आपकी एक पंक्ति की आवश्यकता को भी पूरा करता है और पढ़ने में आसान है।


हां, लेकिन कोड स्पष्ट नहीं है। आपके कितने साथी डेवलपर्स को पता होगा कि आप क्या हासिल करने की कोशिश कर रहे हैं?
AGuyCalledGerald 12

0

भले ही यह एक पुराना सवाल है और ओपी ने C # के लिए कहा, मैं उन लोगों के लिए VB.Net समाधान साझा करना चाहता हूं, जो C # के बजाय VB.Net के साथ काम करते हैं:

Dim myObj As Object = Nothing
Dim s As String = If(myObj, "").ToString()

myObj = 42
s = If(myObj, "").ToString()

Unfortunatly VB.Net अनुमति नहीं देता है? -परिचय के बाद एक चर तो myObj? .ToString मान्य नहीं है (कम से कम .Net 4.5 में नहीं है, जो मैंने समाधान के परीक्षण के लिए उपयोग किया था)। इसके बजाय मैं अगर myObj ist कुछ भी नहीं है तो खाली स्ट्रिंग वापस करने के लिए I का उपयोग करता हूं। इसलिए पहला टोस्ट्रिंग-कॉल एक खाली स्ट्रिंग लौटाता है, जबकि दूसरा (जहां myObj कुछ नहीं है) "42" देता है।

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