String.Empty और "" (खाली स्ट्रिंग) के बीच क्या अंतर है?


288

नेट में, क्या बीच का अंतर है String.Emptyऔर "", और वे परस्पर विनिमय कर रहे हैं, या वहाँ कुछ अंतर्निहित संदर्भ या समानता है कि चारों ओर स्थानीयकरण मुद्दों है String.Emptyयह सुनिश्चित करना होगा एक समस्या नहीं कर रहे हैं?


2
असली सवाल यह नहीं है कि बल्कि क्यों । क्यों Microsoft के साथ आया string.Emptyथा और readonlyइसके बजाय इसे घोषित करने के पीछे तर्क क्या था const
user1451111

जवाबों:


295

संस्करण 2.0 से पहले .NET में, ""ऑब्जेक्ट string.Emptyबनाता है जबकि नो ऑब्जेक्ट रेफरी बनाता है , जो string.Emptyअधिक कुशल बनाता है ।

संस्करण 2.0 और बाद में .NET में, सभी ""स्ट्रिंग एक ही स्ट्रिंग शाब्दिक के संदर्भ में हैं, जिसका अर्थ ""है कि यह समान है .Empty, लेकिन फिर भी उतना तेज़ नहीं है .Length == 0

.Length == 0सबसे तेज़ विकल्प है, लेकिन .Emptyथोड़ा क्लीनर कोड बनाता है।

देखें अधिक जानकारी के लिए नेट विनिर्देश


91
"" स्ट्रिंग इंटर्निंग के कारण केवल एक बार ही किसी वस्तु का निर्माण होगा। मूल रूप से प्रदर्शन ट्रेडऑफ़ मूंगफली है - पठनीयता अधिक महत्वपूर्ण है।
जॉन स्कीट

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

11
मैं सावधान रहूँगा। लघुरूप == 0, क्योंकि यह एक अपवाद फेंक सकता है यदि आपका स्ट्रिंग चर शून्य है। यदि आप इसे "" के विरूद्ध जाँचते हैं, तो यह बिना किसी अपवाद के ठीक से गलत तरीके से वापस आ जाएगा।
जेफरी हार्मन

11
@ जेफ्रीहार्मन: या आप उपयोग कर सकते हैं string.IsNullOrEmpty( stringVar )
फ्लाईन 1179

1
यदि कोई खाली स्ट्रिंग के परीक्षण के लिए बुरे व्यवहार को रोकना चाहता है, तो आप कोड विश्लेषण में CA1820 को सक्षम कर सकते हैं। docs.microsoft.com/visualstudio/code-quality/…
शॉन

197

String.Empty और "" के बीच क्या अंतर है, और क्या वे विनिमेय हैं

string.Emptyएक केवल पढ़ने के लिए मैदान है, जबकि ""एक संकलन समय स्थिर है। वे स्थान जहां वे अलग व्यवहार करते हैं:

C # 4.0 या उच्चतर में डिफ़ॉल्ट पैरामीटर मान

void SomeMethod(int ID, string value = string.Empty)
// Error: Default parameter value for 'value' must be a compile-time constant
{
    //... implementation
}

स्विच स्टेटमेंट में केस एक्सप्रेशन

string str = "";
switch(str)
{
    case string.Empty: // Error: A constant value is expected. 
        break;

    case "":
        break;

}

तर्क वितर्क करें

[Example(String.Empty)]
// Error: An attribute argument must be a constant expression, typeof expression 
//        or array creation expression of an attribute parameter type

21
दिलचस्प है, मुझे नहीं लगता कि इस पुराने सवाल से कोई प्रासंगिक नई जानकारी मिलेगी। मैं गलत था
जॉन्क

मुझे लगता है कि C # 4.0 या उच्चतर में आपका उदाहरण # 1 डिफ़ॉल्ट पैरामीटर मान अनिवार्य रूप से आपके उदाहरण # 3 गुण तर्क का एक डुप्लिकेट है , क्योंकि मेरा मानना ​​है कि .NET डिफ़ॉल्ट मापदंडों को विशेषताओं में तैनात करता है। इसलिए मूल रूप से, आप बस (रन-टाइम) "वैल्यू" नहीं डाल सकते हैं (इस मामले में, स्टिकर्स के लिए एक इंस्टेंस हैंडल ) (कंपाइल-टाइम) मेटाडेटा में।
ग्लेन स्लेडेन

@GlennSlayden, मैं आपसे सहमत नहीं हूँ। प्रारंभिक आरंभीकरण एक साधारण आरंभीकरण से अलग है। ऐसा इसलिए है क्योंकि आप String.Emptyज्यादातर मामलों में एक तर्क के रूप में पारित कर सकते हैं । आप सही हैं कि सभी उदाहरण दिखाते हैं you simply can't put a (run-time) "value" into (compile-time) metadataऔर वह वही है जो उदाहरण दिखाना चाहते हैं।
सासुके उचिहा

42

पिछले उत्तर .NET 1.1 के लिए सही थे (जिस पोस्ट को उन्होंने जोड़ा था उसकी तारीख देखें: 2003)। .NET 2.0 और बाद में, अनिवार्य रूप से कोई अंतर नहीं है। जेआईटी किसी भी तरह से ढेर पर उसी वस्तु को संदर्भित करेगा।

सी # विनिर्देश के अनुसार, खंड 2.4.4.5: http://msdn.microsoft.com/en-us/library/aa691090(VS.71).aspx

प्रत्येक स्ट्रिंग शाब्दिक आवश्यक रूप से एक नए स्ट्रिंग उदाहरण में परिणाम नहीं करता है। जब दो या दो से अधिक स्ट्रिंग शाब्दिक स्ट्रिंग स्ट्रिंग ऑपरेटर (धारा 7.9.7) के अनुसार एक ही विधानसभा में दिखाई देते हैं, तो ये स्ट्रिंग शाब्दिक एक ही स्ट्रिंग उदाहरण को संदर्भित करते हैं।

ब्रैड अब्राम की पोस्ट की टिप्पणियों में भी किसी ने इसका उल्लेख किया है

सारांश में, "" बनाम स्ट्रिंग का व्यावहारिक परिणाम। खाली शून्य है। जेआईटी अंत में इसका पता लगाएगी।

मैंने पाया है, व्यक्तिगत रूप से, कि जेआईटी मेरे मुकाबले अधिक स्मार्ट है और इसलिए मैं कोशिश करता हूं कि इसके बाद माइक्रो-कंपाइलर अनुकूलन के साथ बहुत चालाक न हो। JIT () लूप्स के लिए प्रकट होगा, निरर्थक कोड, इनलाइन विधियों आदि को बेहतर तरीके से हटा देगा और अधिक उपयुक्त समय पर या तो I या C # कंपाइलर कभी भी हाथ से पहले अनुमान लगा सकता है। JIT को अपना काम करने दें :)


1
छोटा टाइपो? "जेआईटी किसी भी तरह से मदद पर उसी वस्तु को संदर्भित करेगा।" क्या आपका मतलब "ढेर पर" था?
दाना

संबंधित लोकप्रिय सवाल stackoverflow.com/questions/263191/…
माइकल फ्रीजिम

36

String.Emptyएक कॉन्स्टेबल फील्ड है, जबकि ""एक कॉन्स्टेबल है । इसका मतलब है कि आप String.Emptyस्विच स्टेटमेंट में उपयोग नहीं कर सकते क्योंकि यह एक स्थिर नहीं है।


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

18

एक और अंतर यह है कि String.Empty बड़ा CIL कोड बनाता है। जबकि "" और स्ट्रिंग के संदर्भ के लिए कोड। String.Empty समान लंबाई है, स्ट्रिंग स्ट्रिंग के लिए कंपेन स्ट्रिंग स्ट्रिंग (एरिक लिपर्ट के ब्लॉग पोस्ट देखें ) का अनुकूलन नहीं करता है। खाली तर्क। निम्नलिखित समतुल्य कार्य

string foo()
{
    return "foo" + "";
}
string bar()
{
    return "bar" + string.Empty;
}

यह आईएल उत्पन्न करें

.method private hidebysig instance string foo() cil managed
{
    .maxstack 8
    L_0000: ldstr "foo"
    L_0005: ret 
}
.method private hidebysig instance string bar() cil managed
{
    .maxstack 8
    L_0000: ldstr "bar"
    L_0005: ldsfld string [mscorlib]System.String::Empty
    L_000a: call string [mscorlib]System.String::Concat(string, string)
    L_000f: ret 
}

मान्य बिंदु लेकिन ऐसी बात कौन करेगा? मुझे किसी उद्देश्य के लिए एक खाली स्ट्रिंग को क्यों बदलना चाहिए?
रॉबर्ट एस।

@RobertS। शायद दूसरा स्ट्रिंग एक अलग फ़ंक्शन में था जो इनलेट हो गया। यह दुर्लभ है, मैं आपको अनुदान देता हूं।
ब्रूनो मार्टिनेज

3
यह त्रिगुट ऑपरेटर का उपयोग कि दुर्लभ नहीं है:"bar " + (ok ? "" : "error")
symbiont

13

उपरोक्त उत्तर तकनीकी रूप से सही हैं, लेकिन आप वास्तव में क्या उपयोग करना चाहते हैं, सर्वोत्तम कोड पठनीयता के लिए और अपवाद का कम से कम मौका String.IsNullOrEmpty (s) है


3
समानता की तुलना के संदर्भ में, मैं पूरी तरह से सहमत हूं, लेकिन सवाल दो अवधारणाओं के बीच अंतर के साथ-साथ तुलना के बारे में भी था
जॉंच

1
सावधान रहें कि "अपवाद का कम से कम मौका" अक्सर "जारी रखने का सबसे मौका है लेकिन कुछ गलत कर रहा है"। उदाहरण के लिए, यदि आपके पास एक कमांड लाइन तर्क है जिसे आप पार्स कर रहे हैं और कोई व्यक्ति आपके ऐप को कॉल करता है, --foo=$BARतो आप शायद उन दोनों के बीच अंतर को स्पॉट करना चाहते हैं जो एक एनवी var सेट करना भूल जाते हैं और वे ध्वज को बिल्कुल भी नहीं गुजारते हैं। string.IsNullOrEmptyअक्सर एक कोड-गंध है जो आपने अपने इनपुट को ठीक से मान्य नहीं किया है या अजीब चीजें कर रहे हैं। जब आप वास्तव में उपयोग करने के लिए nullया शायद एक प्रकार / विकल्प प्रकार की तरह मतलब है , तो आपको आम तौर पर खाली तारों को स्वीकार नहीं करना चाहिए ।
एलिस्टेयर मोव

11

मैं एक सरल के String.Emptyबजाय उपयोग करना चाहता हूं "", फिर भी स्पष्ट कारण नहीं है: ""और"" न ही समान हैं, पहले वाले में वास्तव में 16 शून्य चौड़ाई वर्ण हैं। जाहिर है कि कोई भी सक्षम डेवलपर अपने कोड में चौड़ाई पात्रों को डालने और डालने वाला नहीं है, लेकिन अगर वे वहां पहुंचते हैं, तो यह एक रखरखाव दुःस्वप्न हो सकता है।

टिप्पणियाँ:

  • मैंने इस उदाहरण में U + FEFF का उपयोग किया ।

  • यकीन नहीं होता कि एसओ उन पात्रों को खाने जा रहा है, लेकिन कई शून्य-चौड़ाई वाले पात्रों में से एक के साथ खुद को आज़माएं

  • मैं केवल इस पर आया था https://codegolf.stackexchange.com/


यह अधिक उत्थान के योग्य है। मैंने देखा है कि प्लेटफ़ॉर्म पर सिस्टम इंटीग्रेशन के माध्यम से यह समस्या होती है।
EvilDr

8

के String.Emptyबजाय का उपयोग करें ""

यह मेमोरी उपयोग की तुलना में गति के लिए अधिक है लेकिन यह एक उपयोगी टिप है। ""एक शाब्दिक तो एक शाब्दिक रूप में कार्य करेगा है: पहले उपयोग पर यह बनाई गई है और निम्न उपयोगों के लिए अपने संदर्भ दिया जाता है। केवल एक ही उदाहरण को ""मेमोरी में संग्रहीत किया जाएगा चाहे हम कितनी बार इसका उपयोग करें! मुझे यहाँ कोई स्मृति दंड नहीं दिखता है। समस्या यह है कि हर बार ""उपयोग किए जाने के बाद, ""आंतरिक पूल में पहले से ही है या नहीं , इसकी तुलना करने के लिए एक तुलना लूप निष्पादित किया जाता है। दूसरी तरफ, .NET फ्रेमवर्क मेमोरी ज़ोन में संग्रहीत के String.Empty लिए एक संदर्भ है । ?""String.EmptyVB.NET और C # एप्लिकेशन के लिए समान मेमोरी एड्रेस की ओर इशारा करता है। इसलिए "" जब आपको उस संदर्भ में आवश्यकता हो तो हर बार एक संदर्भ की खोज करेंString.Empty

संदर्भ: String.Emptyबनाम""


2
यह सच नहीं है क्योंकि .net 2.0
nelsontruran

6

String.Empty एक ऑब्जेक्ट नहीं बनाता है जबकि "" करता है। हालांकि, जैसा कि यहां बताया गया है , अंतर, तुच्छ है।


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

6

"" के सभी उदाहरण समान हैं, इंटर्न स्ट्रिंग स्ट्रिंग शाब्दिक (या उन्हें होना चाहिए)। इसलिए आप वास्तव में हर बार आपके द्वारा उपयोग किए जाने वाले ढेर पर एक नई वस्तु नहीं फेंकेंगे "" लेकिन केवल उसी, आंतरिक वस्तु का संदर्भ बनाते हुए। ऐसा कहने के बाद, मैं स्ट्रिंग पसंद करता हूं। खाली। मुझे लगता है कि यह कोड को अधिक पठनीय बनाता है।



4
string mystring = "";
ldstr ""

ldstr मेटाडेटा में संग्रहीत स्ट्रिंग शाब्दिक के लिए एक नया ऑब्जेक्ट संदर्भ धक्का देता है।

string mystring = String.Empty;
ldsfld string [mscorlib]System.String::Empty

ldsfld मूल्यांकन स्टैक पर स्थिर क्षेत्र का मान बढ़ाता है

मैं String.Emptyइसके बजाय उपयोग करना चाहता हूं ""क्योंकि IMHO यह स्पष्ट और कम VB-ish है।


3

एरिक लिपर्ट ने लिखा (17 जून, 2013):
"सी एल्गोरिथ्म में मैंने जो पहला एल्गोरिथ्म कभी काम किया था, वह ऑप्टिमाइज़र था, जो स्ट्रिंग कॉन्टेनेनेशन को संभालता है। दुर्भाग्य से मैंने इसे छोड़ने से पहले रोसलिन कोडबेस को इन ऑप्टिमाइज़ेशन को पोर्ट करने का प्रबंधन नहीं किया; उम्मीद है कि कोई होगा उस के लिए जाओ! "

जनवरी 2019 तक कुछ रोसलिन x64 परिणाम यहां दिए गए हैं। इस पृष्ठ पर अन्य उत्तरों की सर्वसम्मति टिप्पणियों के बावजूद, यह मुझे नहीं दिखता है कि वर्तमान x64 JIT इन सभी मामलों को पहचानता है, जब सभी को कहा जाता है और किया जाता है।

विशेष रूप से ध्यान दें, हालांकि, इनमें से केवल एक उदाहरण वास्तव में कॉलिंग को समाप्त करता है String.Concat, और मैं अनुमान लगा रहा हूं कि यह अस्पष्टता शुद्धता कारणों के लिए है (जैसा कि एक अनुकूलन निरीक्षण के विपरीत)। अन्य अंतर समझाने में कठिन लगते हैं।


डिफ़ॉल्ट (स्ट्रिंग) + {डिफ़ॉल्ट (स्ट्रिंग), "", String.Empty}

static String s00() => default(String) + default(String);
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    add  rsp,28h
    ret

static String s01() => default(String) + "";
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    add  rsp,28h
    ret

static String s02() => default(String) + String.Empty;
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    mov  rdx,rax
    test rdx,rdx
    jne  _L
    mov  rdx,rax
_L: mov  rax,rdx
    add  rsp,28h
    ret

"" + {डिफ़ॉल्ट (स्ट्रिंग), "", String.Empty}

static String s03() => "" + default(String);
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    add  rsp,28h
    ret

static String s04() => "" + "";
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    add  rsp,28h
    ret

static String s05() => "" + String.Empty;
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    mov  rdx,rax
    test rdx,rdx
    jne  _L
    mov  rdx,rax
_L: mov  rax,rdx
    add  rsp,28h
    ret

String.Empty + {default (स्ट्रिंग), "", String.Empty}

static String s06() => String.Empty + default(String);
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    mov  rdx,rax
    test rdx,rdx
    jne  _L
    mov  rdx,rax
_L: mov  rax,rdx
    add  rsp,28h
    ret

static String s07() => String.Empty + "";
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    mov  rdx,rax
    test rdx,rdx
    jne  _L
    mov  rdx,rax
_L: mov  rax,rdx
    add  rsp,28h
    ret

static String s08() => String.Empty + String.Empty;
    mov  rcx,[String::Empty]
    mov  rcx,qword ptr [rcx]
    mov  qword ptr [rsp+20h],rcx
    mov  rcx,qword ptr [rsp+20h]
    mov  rdx,qword ptr [rsp+20h]
    call F330CF60                 ; <-- String.Concat
    nop
    add  rsp,28h
    ret


परीक्षण विवरण

Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
AMD64 Release
[MethodImpl(MethodImplOptions.NoInlining)]
'SuppressJitOptimization' = false

2

एंटिटी फ्रेमवर्क के दृष्टिकोण से इस पर आ रहा है: EF संस्करण 6.1.3 स्ट्रींग का इलाज करता है। खाली और मान्य होने पर "" अलग तरीके से।

string.Empty को सत्यापन के प्रयोजनों के लिए एक शून्य मान के रूप में माना जाता है और यदि यह आवश्यक (आरोपित) फ़ील्ड पर उपयोग किया जाता है तो सत्यापन त्रुटि को फेंक देगा; जहां "" सत्यापन मान्य होगा और त्रुटि को नहीं फेंकेगा।

यह समस्या EF 7+ में हल हो सकती है। संदर्भ: - https://github.com/aspnet/EntityFramework/issues/2610 )।

संपादित करें: [आवश्यक (AllowEmptyStrings = true)] इस समस्या को हल करेगा, स्ट्रिंग को अनुमति देने के लिए।


2

चूंकि String.Empty एक संकलन-समय स्थिर नहीं है, इसलिए आप इसे फ़ंक्शन परिभाषा में डिफ़ॉल्ट मान के रूप में उपयोग नहीं कर सकते।

public void test(int i=0,string s="")
    {
      // Function Body
    }

1
इस उत्तर से केवल सारांश: public void test(int i=0, string s=string.Empty) {}संकलित नहीं करेंगे और कहेंगे कि "s 'के लिए डिफ़ॉल्ट पैरामीटर मान एक संकलन-समय स्थिर होना चाहिए। OP का उत्तर काम करता है।
Bugybunny

1

जब आप कोड के माध्यम से नेत्रहीन स्कैनिंग कर रहे हैं, तो "" जिस तरह से तार रंगे हुए हैं, उसे रंगा हुआ दिखाई देता है। string.Empty एक नियमित वर्ग-सदस्य-पहुंच की तरह दिखता है। एक त्वरित नज़र के दौरान, इसका आसान स्थान "" या अर्थ को अंतर करना।

स्ट्रिंग्स को स्पॉट करें (स्टैक ओवरफ्लो कलराइजेशन बिल्कुल मदद नहीं कर रहा है, लेकिन वीएस में यह अधिक स्पष्ट है):

var i = 30;
var f = Math.Pi;
var s = "";
var d = 22.2m;
var t = "I am some text";
var e = string.Empty;

2
आप एक अच्छा बिंदु बनाते हैं, लेकिन क्या डेवलपर वास्तव में "" था? शायद वे अभी तक अज्ञात मूल्य के रूप में कुछ में डाल दिया और लौटने के लिए भूल गए? string.Empty का आपको यह विश्वास दिलाने का लाभ है कि मूल लेखक वास्तव में string का अर्थ है। खाली। इसका एक मामूली बिंदु मुझे पता है।
mark_h

इसके अलावा, एक दुर्भावनापूर्ण (या लापरवाह) डेवलपर उपयुक्त भागने अनुक्रम का उपयोग करने के बजाय उद्धरणों के बीच एक शून्य-चौड़ाई वाला चरित्र डाल सकता है \u00ad
पालेक

-8

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

string str=null;
Console.WriteLine(str.Length);  // Exception(NullRefernceException) for pointing to null reference. 


string str = string.Empty;
Console.WriteLine(str.Length);  // 0

तो ऐसा लगता है कि "नल" का मतलब बिल्कुल शून्य है और "स्ट्रिंग। खाली" का मतलब है कि इसमें किसी प्रकार का मूल्य है, लेकिन यह खाली है।


7
ध्यान दें कि प्रश्न ""बनाम के बारे में है string.Empty। केवल यह बताने की कोशिश की जा रही है कि क्या स्ट्रिंग खाली है, nullइसका उल्लेख किया गया था।
पलक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.