जाँच करना कि क्या कोई वस्तु C # में अशक्त है


226

मैं एक वस्तु पर आगे के प्रसंस्करण को रोकना चाहूंगा अगर यह शून्य है।

निम्नलिखित कोड में मैं जांचता हूं कि क्या वस्तु या तो शून्य है:

if (!data.Equals(null))

तथा

if (data != null)

हालाँकि, मैं एक NullReferenceExceptionपर प्राप्त करते हैं dataList.Add(data)। यदि वस्तु अशक्त थी, तो उसे कभी भी प्रवेश नहीं करना चाहिए if!

इस प्रकार, मैं पूछ रहा हूँ कि क्या यह जाँचने का उचित तरीका है कि क्या कोई वस्तु अशक्त है:

public List<Object> dataList;
public  bool AddData(ref Object data)
    bool success = false;
    try
    {
        // I've also used "if (data != null)" which hasn't worked either
        if (!data.Equals(null))
        {
           //NullReferenceException occurs here ...
           dataList.Add(data);
           success = doOtherStuff(data);
        }
    }
    catch (Exception e)
    {
        throw new Exception(e.ToString());
    }
    return success;
}

यदि यह जाँचने का उचित तरीका है कि क्या वस्तु अशक्त है, तो मैं क्या गलत कर रहा हूँ (मैं NullReferenceException से बचने के लिए ऑब्जेक्ट पर आगे की प्रक्रिया को कैसे रोक सकता हूँ)?


13
आपको throw e;throw new Exception(e.ToString());
निक्स

17
C # में आपको हमेशा != nullअपने अशक्त चेक का उपयोग करना चाहिए । .Equalsहमेशा एक अपवाद फेंक देंगे यदि वस्तु अशक्त है।
काइल ट्रुबरमैन

42
@ निक्स: throw e;ज्यादा बेहतर नहीं है। throw;दूसरी ओर ...
जॉन

4
@ डिवेलपर: e.ToString()एक स्ट्रिंग का उत्पादन करेगा जिसमें न केवल त्रुटि संदेश शामिल है, बल्कि उन सभी InnerExceptionsऔर स्टैक ट्रेस भी शामिल हैं। तो यह एक बहुत ही मोटा-भारी अपवाद संदेश है। यदि आप (सही तरीके से!) इस जानकारी को संरक्षित करना चाहते हैं, और इसे जहां रखना है, बस उपयोग करें throw;
जॉन

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

जवाबों:


252

ऐसा नहीं dataहै null, लेकिन है dataList

आप के साथ एक बनाने की जरूरत है

public List<Object> dataList = new List<Object>();

इससे भी बेहतर: चूंकि यह एक क्षेत्र है, इसलिए इसे बनाएं private। और अगर आपको रोकने के लिए कुछ भी नहीं है, तो इसे भी बनाएं readonly। बस अच्छा अभ्यास है।

अलग

अशक्तता की जाँच करने का सही तरीका है if(data != null)। इस प्रकार की जाँच संदर्भ प्रकारों के लिए सर्वव्यापी है; यहां तक Nullable<T>कि समानता ऑपरेटर को nullable.HasValueशून्यता की जांच करते समय व्यक्त करने का अधिक सुविधाजनक तरीका माना जाता है ।

यदि आप करते हैं if(!data.Equals(null))तो आप एक मिल जाएगा NullReferenceExceptionयदि data == null। इस अपवाद को टालने के बाद से यह किस तरह का हास्य है, पहली जगह में लक्ष्य था।

आप यह भी कर रहे हैं:

catch (Exception e)
{
    throw new Exception(e.ToString());
}

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


5
मैंने इस उद्देश्य के लिए Object.ReferenceEquals (obj, null) भी देखा है । क्या यह समानता पर हावी होने से बचना है?
लुका

2
@LucaPiccioni मैं इसे का उपयोग किया है को रोकने के लिए मूल्य-प्रकार-शिकायत जब जेनरिक का उपयोग कर: geekality.net/2009/11/13/generics-and-checking-for-null
Svish

4
मैं पसंद करता हूं null != data। निरंतर डालने से पहले अस्थि टाइपो null = dataको अनजाने असाइनमेंट के बजाय संकलक त्रुटि में बदल दिया जाता है । (इसके लिए भी काम करता है ==।)
jpmc26

6
@ jpmc26: C # if (data = null)में पहले से ही एक संकलन समय त्रुटि है, इसलिए भले ही वहां पहुंचने में दशकों लग गए हों, लेकिन हमें अब उसके लिए बाहर देखने की जरूरत नहीं है। यहां तक ​​कि C ++ कंपाइलर आसानी से उस कोड के लिए संभव अनपेक्षित असाइनमेंट के बारे में चेतावनी का उत्पादन करेंगे।
जॉन

लुका, आप भी परीक्षण में 'ऑब्जेक्ट' के लिए कास्टिंग करके समानता ओवरराइड से बच सकते हैं। एक समान नस पर, इस उत्तर को इसके बजाय यह दावा करना चाहिए: "यदि ((वस्तु) डेटा! = अशक्त") क्योंकि यह त्रुटियों से बचा जाता है जब समानता को समाप्त कर दिया गया है।
DAG

81

C #> 7.0 उपयोग में

if (obj is null) ...

यह ऑब्जेक्ट द्वारा परिभाषित किसी भी == या! = को अनदेखा करेगा (जब तक कि निश्चित रूप से आप उनका उपयोग नहीं करना चाहते ...)

शून्य उपयोग if (obj is object)(या if (!(obj is null))) के लिए नहीं


1
मुझे आश्चर्य है कि वहाँ एक "शून्य नहीं है"? (अजगर कहता है obj is not null)
1

1
क्यों बेहतर है कि अगर (obj! = Null) से अधिक पठनीय है
Orn Kristjansson

38
काश वे लागू होता if (obj aint null):(
निक बुल

9
क्योंकि वहाँ शून्य नहीं हैif (obj is object)
yatskovsky

3
@OrnKristjansson क्योंकि! = और == को ओवरराइड किया जा सकता है।
मितेच्ल्ज

61

C # 6 में मौद्रिक अशक्त जाँच है :)

इससे पहले:

if (points != null) {
    var next = points.FirstOrDefault();
    if (next != null && next.X != null) return next.X;
}   
return -1;

उपरांत:

var bestValue = points?.FirstOrDefault()?.X ?? -1;

7
क्योंकि "टिप्पणियाँ केवल 5 मिनट के लिए संपादित की जा सकती हैं"? क्या? किसी भी तरह ... जैसा कि मुझे मिल रहा था..मैं व्यक्त करने के लिए एक बेहतर वाक्यविन्यास की तलाश में यहां आया था result = myObject == null ? null : myObject.SomePropertyऔर आपके उदाहरण ने मुझे लिखने के लिए बंद कर दिया result = myObject?.SomeProperty। आदमी!! वह डरपोक है। मुझे अभी भी कोडिंग बहुत पसंद है ...
एडम कॉक्स

27

आपका डेटालिस्ट शून्य है क्योंकि इसे तुरंत पोस्ट नहीं किया गया है, जिस कोड को आपने पोस्ट किया है।

प्रयत्न:

public List<Object> dataList = new List<Object>();
public  bool AddData(ref Object data)
bool success = false;
try
{
    if (!data.Equals(null))   // I've also used if(data != null) which hasn't worked either
    {
       dataList.Add(data);                      //NullReferenceException occurs here
       success = doOtherStuff(data);
    }
}
catch (Exception e)
{
    throw new Exception(e.ToString());
}
return success;

}


3
इसके अलावा, केवल जोड़ने के लिए, यदि डेटा शून्य है, तो यह क्रैश नहीं होगा, आप सूची <ऑब्जेक्ट> में नल जोड़ सकते हैं।
द्वादश

7
लेकिन करने की कोशिश कर रहा है। एक अशक्त पर अपवाद एक अपवाद फेंक देंगे। करना चाहिए! =
Null

@glosrob: आह !! क्या एक निरीक्षण! मैं सोच रहा था कि NullReferenceException ऑब्जेक्ट से थी .. सूची से नहीं! मैं c # में नया हूँ और मुझे लगा कि c # में नल की जाँच करने का एक विशेष तरीका है!
डेवलपर

वह भी, लेकिन मैंने देखा कि एड एस ने इसे कवर किया था।
द्वादशा

1
@ डेवशॉ: सिर ऊपर करने के लिए धन्यवाद। मैं बाद में प्रसंस्करण के लिए जोड़ा जा रहा एक अशक्त वस्तु से बचना चाहता हूं, इसलिए मैं अभी भी एक जांच करूंगा। :)
डेवलपर

19

[@ Kelton52 द्वारा संकेत दर्शाने के लिए संपादित]

सबसे सरल तरीका है object.ReferenceEquals(null, data)

चूंकि (null==data)काम करने की गारंटी नहीं है:

class Nully
{
    public static bool operator ==(Nully n, object o)
    {
        Console.WriteLine("Comparing '" + n + "' with '" + o + "'");
        return true;
    }
    public static bool operator !=(Nully n, object o) { return !(n==o); }
}
void Main()
{
    var data = new Nully();
    Console.WriteLine(null == data);
    Console.WriteLine(object.ReferenceEquals(null, data));
}

पैदा करता है:

'' Nully '' के साथ तुलना

सच

असत्य


1
वास्तव में मैंने सिर्फ यह कोशिश की, और टिप्पणी 'निहित लाभ यह है कि यह किसी भी ओवरराइड को अनदेखा करता है जो डेटा के वर्ग में मौजूद हो सकता है, जैसे "ऑपरेटर! ="। यह सच नहीं लगता।
केली एल्टन

9

नहीं, आपको उपयोग करना चाहिए !=। यदि dataवास्तव में अशक्त है, तो आपका कार्यक्रम विधि NullReferenceExceptionको कॉल करने के प्रयास के परिणामस्वरूप दुर्घटनाग्रस्त हो जाएगा । यह भी महसूस करें कि, यदि आप विशेष रूप से संदर्भ समानता के लिए जांच करना चाहते हैं, तो आपको विधि का उपयोग करना चाहिए क्योंकि आपको कभी नहीं पता कि कैसे लागू किया गया है।EqualsnullObject.ReferenceEqualsEquals

आपका प्रोग्राम क्रैश हो रहा dataListहै क्योंकि आप इसे कभी भी इनिशियलाइज़ नहीं करते हैं क्योंकि यह अशक्त है।


7

इस मामले में समस्या यह नहीं है कि dataयह अशक्त है। यह है कि dataListस्वयं अशक्त है।

उस स्थान पर जहां आप घोषणा dataListकरते हैं कि आपको एक नई Listवस्तु बनानी चाहिए और इसे चर पर असाइन करना चाहिए ।

List<object> dataList = new List<object>();

5

@Jose Ortega उत्तर के अलावा , इसका उपयोग विस्तार विधि के लिए बेहतर है

 public static bool IsNull(this object T)
     {
        return T == null;
     } 

और IsNullसभी के लिए विधि का उपयोग करें जैसे:

object foo = new object(); //or any object from any class
if (foo.IsNull())
   {
     // blah blah //
   }

1
return T == null ? true : false;सिर्फ और सिर्फ क्यों return T == null;?
md2perpe

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

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

मैं कहना चाहता हूँ कि आप विलुप्त होने की विधि के साथ ... कोड हो सकता है कुछ समस्या है और सुधार कर सकते हैं!
अली

आप एक अशक्त वस्तु पर विस्तार विधि कह सकते हैं; आपको बस सावधान रहने के लिए नल (इस मामले में) की तुलना करने की आवश्यकता है। जेमी सही है, हालांकि, यह अजीब लगता है।
टिम बैरास

3

C # 8 के रूप में आप 'रिक्त' संपत्ति पैटर्न ( पैटर्न मिलान के साथ ) का उपयोग यह सुनिश्चित करने के लिए कर सकते हैं कि कोई वस्तु अशक्त नहीं है :

if (obj is { })
{
    // 'obj' is not null here
}

इस दृष्टिकोण का अर्थ है " यदि वस्तु किसी वस्तु का उदाहरण देती है " (अर्थात यह शून्य नहीं है)।

आप इसके विपरीत के बारे में सोच सकते हैं if (obj is null)...:। जब वस्तु किसी वस्तु का संदर्भ नहीं देती है, तो यह सच होगा।

C # 8.0 में पैटर्न के बारे में अधिक जानकारी के लिए यहां पढ़ें ।


3

के रूप में सी # 9 आप कर सकते हैं

if (obj is null) { ... }

अशक्त उपयोग के लिए नहीं

if (obj is not object) { ... }

यदि आपको इस व्यवहार उपयोग ==और उसके !=अनुसार ओवरराइड करने की आवश्यकता है ।


2

जेफरी एल व्हाइटलेज सही है। आपका `dataList`-Object अपने आप में अशक्त है।

आपके कोड के साथ एक और समस्या है: आप रेफ-कीवर्ड का उपयोग कर रहे हैं, जिसका अर्थ है कि तर्क डेटा शून्य नहीं हो सकता है! MSDN कहता है:

एक रेफरी पैरामीटर को पास किया गया तर्क पहले आरम्भ में होना चाहिए। यह अलग-अलग है, जिनके तर्क पास होने से पहले स्पष्ट रूप से आरंभिक नहीं होते हैं

यह `Object´ प्रकार के साथ जेनरिक का उपयोग करने के लिए भी एक अच्छा विचार नहीं है। जेनरिक को बॉक्सिंग / अनबॉक्सिंग से बचना चाहिए और टाइप सुरक्षा भी सुनिश्चित करनी चाहिए। यदि आप एक सामान्य प्रकार चाहते हैं तो अपनी विधि को सामान्य बनाएं। अंत में आपका कोड इस तरह दिखना चाहिए:

public class Foo<T> where T : MyTypeOrInterface {

      public List<T> dataList = new List<T>();

      public bool AddData(ref T data) {
        bool success = false;
        try {
          dataList.Add(data);                   
          success = doOtherStuff(data);
        } catch (Exception e) {
          throw new Exception(e.ToString());
        }
        return success;
      }

      private bool doOtherStuff(T data) {
        //...
      }
    }

2

जैसा कि अन्य लोग पहले ही बता चुके हैं, ऐसा नहीं है data, बल्कि इसकी संभावना dataListहै null। इसके अतिरिक्त...

catch- throwएक एंटीपार्टर्न है जो लगभग हमेशा मुझे हर बार फेंकना चाहता है जो मैं इसे देखता हूं। कल्पना करें कि किसी चीज़ को doOtherStuff()कॉल करने पर कुछ गहरा हो जाता है । तुम सब वापस पाने के लिए एक है Exceptionवस्तु, पर फेंके throwमें AddData()। समस्या के वास्तविक स्रोत को इंगित करने के लिए कोई स्टैक ट्रेस, कोई कॉल जानकारी, कोई राज्य, कुछ भी नहीं, जब तक कि आप अंदर न जाएं और अपने डिबगर को अपवाद के बजाय फेंक दिए गए अपवाद पर तोड़ने के लिए स्विच न करें। आप एक अपवाद को पकड़ने रहे हैं और इसे फिर से फेंक, तो किसी भी तरह से , खासकर अगर कोशिश ब्लॉक में कोड nontrivial किसी भी तरह से है, अपने आप को (और आपके सहयोगियों, वर्तमान और भविष्य) एक एहसान करो और पूरे बाहर फेंक try- catchब्लॉक । स्वीकृत,throw;विकल्पों से बेहतर है, लेकिन आप अभी भी अपने आप को दे रहे हैं (या जो कोई भी कोड में बग को ठीक करने की कोशिश कर रहा है) पूरी तरह से अनावश्यक सिरदर्द। यह कहना नहीं है कि ट्राइ-कैच-थ्रो आवश्यक रूप से प्रति सेशन है, जब तक आप अपवाद ऑब्जेक्ट के साथ कुछ प्रासंगिक करते हैं जो कैच ब्लॉक के अंदर फेंका गया था

फिर Exceptionपहली जगह में पकड़ने की संभावित समस्याएं हैं , लेकिन यह एक और मामला है, खासकर जब से इस विशेष मामले में आप एक अपवाद फेंकते हैं।

एक और चीज जो मुझे थोड़ा खतरनाक से ज्यादा प्रभावित करती है, वह dataयह है कि फ़ंक्शन के निष्पादन के दौरान संभावित रूप से मूल्य बदल सकते हैं, क्योंकि आप संदर्भ से गुजर रहे हैं। तो अशक्त चेक पास हो सकता है लेकिन कोड को मूल्य के साथ कुछ भी करने से पहले, यह बदल गया है - शायद null। मैं सकारात्मक नहीं हूं अगर यह चिंता का विषय है या नहीं (यह नहीं हो सकता है), लेकिन यह देखने लायक है।


2
  public static bool isnull(object T)
  {
      return T == null ? true : false;
  }

उपयोग:

isnull(object.check.it)

सशर्त उपयोग:

isnull(object.check.it) ? DoWhenItsTrue : DoWhenItsFalse;

अपडेट (दूसरा तरीका) 08/31/2017 अपडेट किया गया। टिप्पणी के लिए धन्यवाद।

public static bool isnull(object T)
{
    return T ? true : false;
}

5
cond ? true : false;पूरी तरह से बस के बराबर है cond। यह कुछ नहीं जोड़ता है।
lericson

मुझे क्षमा करें, लेकिन यदि आप फ़ंक्शन की जांच करते हैं तो उसे एक बूल मान वापस करना होगा। मैं औपचारिकता कर रहा हूं। इसलिए इसे फिर से जांचें
जोस ऑर्टेगा

3
वह return T == null;भी एक बूलियन देता है!
MQoder 15

मुझे पता है कि संकोच क्या है। ty
जोस ऑर्टेगा

1
इसके बजाय return T == null ? true : false;सिर्फ उपयोग करें return T == null;
md2perpe

1

जब भी आप कक्षा की वस्तुओं का निर्माण कर रहे हैं, तो आपको यह जांचना होगा कि वस्तु नीचे दिए गए कोड का उपयोग कर रही है या नहीं।

उदाहरण: object1 वर्ग की वस्तु है

void myFunction(object1)
{
  if(object1!=null)
  {
     object1.value1 //If we miss the null check then here we get the Null Reference exception
  }
}

0

मैंने सिर्फ एक विधि का पालन किया, जिसे हम आमतौर पर जावा स्क्रिप्ट में फॉलो करेंगे। ऑब्जेक्ट को स्ट्रिंग में बदलने के लिए और फिर जांचें कि क्या वे अशक्त हैं।

var obj = new Object();
var objStr = obj.ToString();
if (!string.IsNullOrEmpty(objStr)){
  // code as per your needs
}

0

मैंने और अधिक सरल (सकारात्मक तरीका) किया और यह अच्छी तरह से काम करता है।

चूंकि किसी भी प्रकार की "वस्तु" कम से कम एक वस्तु है


    if (MyObj is Object)
    {
            //Do something .... for example:  
            if (MyObj is Button)
                MyObj.Enabled = true;
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.