VB.NET और C # में एक मान के खिलाफ अशक्तता की जाँच करने में अंतर क्यों है?


110

में VB.NET होता है:

Dim x As System.Nullable(Of Decimal) = Nothing
Dim y As System.Nullable(Of Decimal) = Nothing

y = 5
If x <> y Then
    Console.WriteLine("true")
Else
    Console.WriteLine("false") '' <-- I got this. Why?
End If

लेकिन C # में ऐसा होता है:

decimal? x = default(decimal?);
decimal? y = default(decimal?);

y = 5;
if (x != y)
{
    Debug.WriteLine("true"); // <-- I got this -- I'm with you, C# :)
}
else
{
    Debug.WriteLine("false");
}

ये अंतर क्यों है?


22
यह भयानक है।
मिकब

8
मेरा मानना default(decimal?)है कि 0 लौटा रहा है , नहीं null
रयान फ्रेम

7
@RyanFrame NO। चूंकि यह अशक्त प्रकार है , इसलिए यह वापस लौटता हैnull
सोनर ग्नुएल

4
अरे हाँ ... सही है ... VB Ifकंडीशन में बूलियन के रूप में मूल्यांकन करने की आवश्यकता नहीं होती है ... uuuugh EDIT: तो Nothing <> Anything = Nothingजिसके परिणामस्वरूप Ifनकारात्मक / अन्य मार्ग लिया जाता है।
क्रिस सिनक्लेयर

13
@ जेएमके: अशक्त, कुछ भी नहीं और खाली वास्तव में सभी अलग-अलग हैं। यदि वे सभी समान थे तो आपको उनमें से तीन की आवश्यकता नहीं होगी।
एरिक लिपर्ट

जवाबों:


88

VB.NET और C # .NET अलग-अलग भाषाएं हैं, जो विभिन्न टीमों द्वारा निर्मित हैं जिन्होंने उपयोग के बारे में अलग-अलग धारणाएं बनाई हैं; इस मामले में एक पूर्ण तुलना के शब्दार्थ।

मेरी निजी प्राथमिकता VB.NET शब्दार्थ के लिए है, जो संक्षेप में NULL शब्दार्थ "मुझे अभी तक नहीं पता है" देता है। फिर 5 की तुलना "मुझे अभी तक नहीं पता है"। स्वाभाविक रूप से "मुझे अभी तक पता नहीं है"; यानी NULL। इसमें SQL डेटाबेस में NULL (सबसे अधिक नहीं तो सभी) के व्यवहार को प्रतिबिंबित करने का अतिरिक्त लाभ है। यह भी तीन-मूल्यवान तर्क की एक अधिक मानक (C # 's) व्याख्या है, जैसा कि यहां बताया गया है

C # की टीम ने NULL का मतलब क्या है, इसके बारे में अलग-अलग धारणाएं बनाईं, जिसके परिणामस्वरूप आपके द्वारा दिखाए गए व्यवहार में अंतर होता है। एरिक लिपर्ट ने सी # में NULL के अर्थ के बारे में एक ब्लॉग लिखा था । एरिक लिपर्ट के अनुसार: "मैंने यहाँ और यहाँ VB / VBScript और JScript में नल के शब्दार्थों के बारे में भी लिखा है "।

ऐसे किसी भी वातावरण में जिसमें NULL मान संभव है, यह मान्यता है कि अपवर्जित मध्य का कानून (अर्थात A या ~ A tautologically सत्य है) पर अब भरोसा नहीं किया जा सकता है।

अपडेट करें:

A bool( A के विपरीत bool?) केवल मान TRUE और FALSE ले सकता है। हालाँकि NULL की भाषा कार्यान्वयन यह तय करना चाहिए कि NULL कैसे भावों के माध्यम से प्रचार करता है। VB में भाव 5=nullऔर 5<>nullBOTH गलत है। C # में, तुलनीय भाव 5==nullऔर 5!=nullकेवल दूसरा पहला [अद्यतन 2014-03-02 - PG] गलत है। हालांकि, किसी भी वातावरण में, जो अशक्त का समर्थन करता है, प्रोग्रामर पर उस भाषा द्वारा उपयोग किए जाने वाले सत्य तालिकाओं और अशांति-प्रसार को जानना असंभव है।

अपडेट करें

एरिक लिपर्ट के ब्लॉग लेख (नीचे उनकी टिप्पणियों में उल्लिखित) शब्दार्थ पर हैं:


4
लिंक के लिए धन्यवाद। मैंने यहाँ VB / VBScript और JScript में nulls के शब्दार्थों के बारे में भी लिखा है: blogs.msdn.com/b/ericlippert/archive/2003/09/30/53120.aspx और यहाँ: blogs.msdn.com/b/ericlippert/ संग्रह / 2003/10/01 / 53128.aspx
एरिक

27
और FYI करें VB के साथ C # को असंगत बनाने का निर्णय इस तरह विवादास्पद था। मैं उस समय भाषा डिजाइन टीम में नहीं था लेकिन इस फैसले में बहस की मात्रा काफी थी।
एरिक लिपर्ट

2
@ BlueRaja-DannyPflughoeft C # boolमें 3 मान नहीं हो सकते, केवल दो। यह bool?तीन मान हो सकते हैं। operator ==और operator !=दोनों bool, bool?ऑपरेंड के प्रकार की परवाह किए बिना , नहीं लौटे । इसके अतिरिक्त, एक ifबयान केवल एक स्वीकार कर सकता है bool, नहीं bool?
18

1
C # में भाव 5=nullऔर 5<>nullमान्य नहीं हैं। और की 5 == nullऔर 5 != null, आप यह है कि रिटर्न पीछे नहीं है यकीन है false?
बेन वोइगट

1
@BenVoigt: धन्यवाद। उन सभी वोटों को और आप उस टाइपो को पहली बार देख रहे हैं। ;-)
पीटर गेकर्न्स 22

37

क्योंकि के बदले x <> yलौटता Nothingहै true। यह केवल परिभाषित नहीं है क्योंकि xयह परिभाषित नहीं है। (एसक्यूएल नल के समान)।

नोट: VB.NET Nothing<> C # null

आपको इसके मूल्य की तुलना Nullable(Of Decimal)केवल तभी करनी होगी जब इसका मूल्य हो।

तो ऊपर VB.NET इस के समान तुलना करता है (जो कम गलत दिखता है):

If x.HasValue AndAlso y.HasValue AndAlso x <> y Then
    Console.WriteLine("true")
Else
    Console.WriteLine("false")  
End If

VB.NET भाषा विनिर्देश :

7.1.1 अशक्त मान प्रकार ... एक अशक्त मान प्रकार के मानों के साथ-साथ अशक्त मान के समान मान हो सकते हैं। इस प्रकार, एक अशक्त मान प्रकार के लिए, प्रकार के एक चर के लिए कुछ भी निर्दिष्ट करना शून्य मान के लिए चर का मान सेट करता है, न कि मूल्य प्रकार का शून्य मान।

उदाहरण के लिए:

Dim x As Integer = Nothing
Dim y As Integer? = Nothing

Console.WriteLine(x) ' Prints zero '
Console.WriteLine(y) ' Prints nothing (because the value of y is the null value) '

16
"VB.NET कुछ नहीं <> C # null" क्या यह C # के लिए सही है और VB.Net के लिए गलत है? बस मजाक कर रहे हैं :-p
ken2k

17

जनरेट किए गए CIL को देखें (मैंने दोनों को C # में बदल दिया है):

सी#:

private static void Main(string[] args)
{
    decimal? x = null;
    decimal? y = null;
    y = 5M;
    decimal? CS$0$0000 = x;
    decimal? CS$0$0001 = y;
    if ((CS$0$0000.GetValueOrDefault() != CS$0$0001.GetValueOrDefault()) ||
        (CS$0$0000.HasValue != CS$0$0001.HasValue))
    {
        Console.WriteLine("true");
    }
    else
    {
        Console.WriteLine("false");
    }
}

मूल दृश्य:

[STAThread]
public static void Main()
{
    decimal? x = null;
    decimal? y = null;
    y = 5M;
    bool? VB$LW$t_struct$S3 = new bool?(decimal.Compare(x.GetValueOrDefault(), y.GetValueOrDefault()) != 0);
    bool? VB$LW$t_struct$S1 = (x.HasValue & y.HasValue) ? VB$LW$t_struct$S3 : null;
    if (VB$LW$t_struct$S1.GetValueOrDefault())
    {
        Console.WriteLine("true");
    }
    else
    {
        Console.WriteLine("false");
    }
}

आप देखेंगे कि विज़ुअल बेसिक रिटर्न Nullable <bool> (बूल, असत्य या सत्य नहीं!) में तुलना। और अपरिभाषित जो बूल में परिवर्तित होता है वह असत्य है।

Nothingजो कुछ भी हमेशा होता है Nothing, उसकी तुलना में Visual Basic में गलत नहीं है (यह SQL में जैसा है)।


परीक्षण और त्रुटि से प्रश्न का उत्तर क्यों दें? भाषा विनिर्देशों से इसे करना संभव होना चाहिए।
डेविड हेफर्नन

3
@DavidHeffernan, क्योंकि यह उस भाषा में अंतर दिखाता है जो बहुत असंदिग्ध है।
नथ्रो

2
@Yossarian आपको लगता है कि भाषा चश्मा मुद्दे पर अस्पष्ट हैं। मैं असहमत हूं। आईएल परिवर्तन के लिए एक कार्यान्वयन विस्तार विषय है; चश्मा नहीं हैं।
Servy

2
@DavidHeffernan: मुझे आपका रवैया पसंद है और आप कोशिश करने के लिए प्रोत्साहित करते हैं। VB भाषा विनिर्देश को कई बार पार्स करना मुश्किल हो सकता है। ल्यूसियन अब कुछ वर्षों से इसमें सुधार कर रहा है, लेकिन इस तरह के कोने के मामलों के सटीक अर्थों का पता लगाना अभी भी काफी मुश्किल हो सकता है। मेरा सुझाव है कि आप कल्पना की एक प्रति प्राप्त करें, कुछ शोध करें और अपने निष्कर्षों की रिपोर्ट करें।
एरिक लिपर्ट

2
आईएल कोड आपके द्वारा दिए गए क्रियान्वित करने के परिणामों @Yossarian परिवर्तन के अधीन नहीं है, लेकिन सी # / वीबी प्रदान की आईएल कोड आप से पता चला है में संकलित किया जाएगा कोड है कि है (जब तक कि आईएल है व्यवहार के रूप में परिवर्तन के अधीन यह भी भाषा चश्मा 'परिभाषा) के साथ इनलाइन।
सर्व

6

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

वास्तव में, भ्रम का मूल कारण एक गलत धारणा है कि समानता और असमानता परीक्षण के विभिन्न रूपों को एक ही परिणाम प्राप्त करने की अपेक्षा की जानी चाहिए, इस तथ्य के बावजूद कि विभिन्न परिस्थितियों में विभिन्न शब्दार्थ उपयोगी होते हैं। उदाहरण के लिए, एक अंकगणितीय दृष्टिकोण से, यह उपयोगी होने के लिए सक्षम है Decimalजो केवल अनुगामी शून्य की संख्या में भिन्नता है। इसी doubleतरह सकारात्मक शून्य और नकारात्मक शून्य जैसे मूल्यों के लिए । दूसरी ओर, कैशिंग या इंटर्निंग दृष्टिकोण से, ऐसे शब्दार्थ घातक हो सकते हैं। उदाहरण के लिए, मान लीजिए कि किसी के पास Dictionary<Decimal, String>ऐसा है जो myDict[someDecimal]बराबर होना चाहिए someDecimal.ToString()। यदि किसी के पास बहुत सी वस्तु हो तो यह उचित होगाDecimalवे मान जो स्ट्रिंग में परिवर्तित करना चाहते थे और उम्मीद थी कि कई डुप्लिकेट होंगे। दुर्भाग्य से, अगर इस तरह के कैशिंग का उपयोग 12.3 मीटर और 12.40 मीटर में परिवर्तित करने के लिए किया जाता है, इसके बाद 12.30 मीटर और 12.4 मीटर होता है, तो बाद के मान "12.3" और "12.40" के बजाय "12.30" और "12.4" होंगे।

मामले में वापस लौटना, समानता के लिए अशक्त वस्तुओं की तुलना करने का एक से अधिक समझदार तरीका है। C # उस दृष्टिकोण को लेता है जिसके ==ऑपरेटर को उसके व्यवहार को प्रतिबिंबित करना चाहिए EqualsVB.NET इस दृष्टिकोण को लेता है कि उसके व्यवहार में कुछ अन्य भाषाओं का दर्पण होना चाहिए, क्योंकि कोई भी व्यक्ति जो Equalsव्यवहार का उपयोग कर सकता है Equals। कुछ अर्थों में, सही समाधान के लिए एक तीन-तरफा "यदि" निर्माण होगा, और यह आवश्यक होगा कि यदि सशर्त अभिव्यक्ति तीन-मूल्यवान परिणाम देता है, तो कोड को निर्दिष्ट करना चाहिए कि nullमामले में क्या होना चाहिए । चूंकि वे भाषाओं के साथ एक विकल्प नहीं हैं जैसा कि वे हैं, अगला सबसे अच्छा विकल्प केवल यह सीखना है कि विभिन्न भाषाएं कैसे काम करती हैं और पहचानती हैं कि वे समान नहीं हैं।

संयोग से, विजुअल बेसिक के "इज़" ऑपरेटर, जिसमें सी की कमी है, का उपयोग यह परीक्षण करने के लिए किया जा सकता है कि क्या एक अशक्त वस्तु वास्तव में, अशक्त है। हालांकि, कोई भी यह सवाल कर सकता है कि ifपरीक्षण को स्वीकार करना चाहिए या नहीं Boolean?, सामान्य तुलना करने वाले ऑपरेटरों के पास लौटने के Boolean?बजाय Booleanजब अशक्त प्रकारों के लिए एक उपयोगी विशेषता है। संयोग से, VB.NET में, यदि कोई बजाए समानता ऑपरेटर का उपयोग करने का प्रयास करता है, तो एक को Isचेतावनी मिलेगी कि तुलना का परिणाम हमेशा रहेगा Nothing, और किसी को Isकुछ अशक्त होने पर परीक्षण करना चाहिए ।


परीक्षण करना कि क्या C # में एक कक्षा शून्य है == null। और परीक्षण कि क्या एक अशक्त मूल्य प्रकार के द्वारा किया जाता है .hasValue। एक Is Nothingऑपरेटर के लिए क्या उपयोग है ? C # में है, isलेकिन यह टाइप संगतता के लिए परीक्षण करता है । इन के प्रकाश में, मुझे वास्तव में यकीन नहीं है कि आपका अंतिम पैराग्राफ क्या कहना चाह रहा है।
एरिक

@ErikE: vb.net और C # दोनों को एक तुलना का उपयोग करके मूल्य के लिए अशक्त प्रकारों की जांच करने की अनुमति देता है null, हालांकि दोनों ही भाषाएं HasValueजांच के लिए सिंटैक्टिक शुगर के रूप में व्यवहार करती हैं , कम से कम उन मामलों में जहां प्रकार ज्ञात है (मुझे यकीन नहीं है क्या कोड जेनरिक के लिए उत्पन्न होता है)।
सुपरकैट

जेनेरिक में आप
अशक्त

3

हो सकता है यह पोस्ट आपकी अच्छी मदद करे:

अगर मुझे सही से याद है, तो VB में 'कुछ नहीं' का अर्थ है "डिफ़ॉल्ट मान"। मान प्रकार के लिए, वह डिफ़ॉल्ट मान है, संदर्भ प्रकार के लिए, यह शून्य होगा। इस प्रकार, एक संरचना को कुछ भी नहीं सौंपना, कोई समस्या नहीं है।


3
इस सवाल का जवाब नहीं है।
डेविड हेफर्नन

नहीं, यह कुछ भी स्पष्ट नहीं करता है। सवाल <>वीबी में ऑपरेटर के बारे में है , और यह कैसे अशक्त प्रकारों पर काम करता है।
डेविड हेफर्नन

2

यह वीबी की एक निश्चित विचित्रता है।

VB में, यदि आप दो अशक्त प्रकारों की तुलना करना चाहते हैं, तो आपको उपयोग करना चाहिए Nullable.Equals()

आपके उदाहरण में, यह होना चाहिए:

Dim x As System.Nullable(Of Decimal) = Nothing
Dim y As System.Nullable(Of Decimal) = Nothing

y = 5
If Not Nullable.Equals(x, y) Then
    Console.WriteLine("true")
Else
    Console.WriteLine("false")
End If

5
यह "अजीब" है जब यह परिचित नहीं है। Pieter Geerkens द्वारा दिया गया उत्तर देखें।
rskar

वैसे मुझे यह भी अजीब लगता है कि VB के व्यवहार को पुन: पेश नहीं करता है Nullable<>.Equals()। एक ही तरीके से काम करने की उम्मीद कर सकता है (जो सी # करता है)।
मैथ्यू वाटसन

उम्मीदें, जैसा कि "जो कोई उम्मीद कर सकता है," वह है जो किसी ने अनुभव किया है। C # को Java यूजर्स की उम्मीदों को ध्यान में रखकर बनाया गया था। जावा को C / C ++ उपयोगकर्ताओं की अपेक्षाओं को ध्यान में रखकर बनाया गया था। बेहतर या बदतर के लिए, VB.NET को VB6 उपयोगकर्ताओं की अपेक्षाओं को ध्यान में रखकर डिजाइन किया गया था। पर विचार के लिए अधिक भोजन stackoverflow.com/questions/14837209/... और stackoverflow.com/questions/10176737/...
rskar

1
@MatthewWatson Nullable.NET के पहले संस्करणों में मौजूद नहीं थी, इसे C # और VB.NET द्वारा कुछ समय के लिए बाहर कर दिए जाने के बाद बनाया गया था और पहले से ही उनके अशक्त प्रचार व्यवहार का निर्धारण किया गया था। क्या आप ईमानदारी से उस भाषा के बारे में अपेक्षा करते हैं जो कई वर्षों से नहीं बनाई गई है? VB.NET प्रोग्रामर के दृष्टिकोण से, यह Nullable.Equals है जो भाषा के साथ संगत नहीं है, बल्कि अन्य तरीके से। (यह देखते हुए कि C # और VB दोनों एक ही Nullableपरिभाषा का उपयोग करते हैं , इसके लिए दोनों भाषाओं के अनुरूप होने का कोई तरीका नहीं था।)
Servy

0

आपका VB कोड केवल गलत है - यदि आप "x <> y" को "x = y" में बदलते हैं, तो परिणाम के रूप में आपके पास "गलत" होगा। अशक्त उदाहरणों के लिए यह अभिव्यक्ति का सबसे सामान्य तरीका है "नॉट x.Equals (y)", और इससे C # में "x! Y" के समान व्यवहार होगा।


1
जब तक xहै nothing, जो मामले में x.Equals(y)एक अपवाद फेंक देते हैं।
सेरी

@ सरवी: इस पर फिर से ठोकर खाई (कई साल बाद), और ध्यान दिया कि मैंने आपको सही नहीं किया - "x.Equals (y)" अशक्त प्रकार के उदाहरण 'x' के लिए एक अपवाद नहीं फेंकेगा । संकलक द्वारा अशक्त प्रकारों का अलग तरीके से व्यवहार किया जाता है।
डेव डोकनजस

विशेष रूप से, 'null' के लिए आरंभिक एक अशक्त उदाहरण वास्तव में अशक्त करने के लिए एक चर सेट नहीं है, लेकिन कोई मान सेट के साथ एक System.Nullable उदाहरण है।
डेव डोकनजस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.