2015-10-13 6 views
18

NullReferenceException को संभालने के लिए नीचे दी गई मेरी कोड मुझे देता है एक NullReferenceException और स्टैक ट्रेस मुझसे कहता समस्या Count विधि में है, इसलिए मैं कुछ बिंदु foo, bar या baznull है पर बहुत यकीन है।अच्छा तरीका से पहले सी # 6.0

मेरे कोड:

IQueryable<IGrouping<string, Referral>> queryable= ...; 
var dict = queryable.ToDictionary(g => g.Key.ToString(), 
            g => g.Count(r => r.foo.bar.baz.dummy == "Success")); 

मैं सोच रहा हूँ null मामलों को संभालने के लिए एक संक्षिप्त तरीके से क्या। मैं में है कि सीखना सी # 6.0 मैं सिर्फ foo?.bar?.baz?.dummy कर सकते हैं, हालांकि परियोजना मैं पर काम कर रहा हूँ < 6.0 के लिए एक समाधान हो सकता है सी # 6.0

+0

आपके पास 'g.Count()' के लिए एक अभिव्यक्ति निकाय हो सकता है लेकिन शून्य सशर्त ऑपरेटर लाया गया था क्योंकि ऐसा करने की प्रक्रिया इतनी वर्बोज़ थी। तो दुर्भाग्य से मुझे नहीं लगता कि आप इसे से बचने जा रहे हैं –

+0

आप किस संस्करण का उपयोग कर रहे हैं? या आप किसी भी पूर्व-6.0 समाधान की तलाश में हैं? – LJNielsenDk

+0

यह थोड़ा बदसूरत हो सकता है लेकिन 'g.Count (r => r.foo == null? False: r.foo.bar == null? False: r.foo.bar.baz == null? False: r .foo.bar.baz.dummy == "सफलता") '? –

उत्तर

30

नहीं है:

.Count(r => r.foo != null && 
      r.foo.bar != null && 
      r.foo.bar.baz != null && 
      r.foo.bar.baz.dummy == "Success") 
वास्तव में की तरह जटिल निर्माणों के लिए

शून्य प्रक्षेपण ऑपरेटर के ऊपर एक पेश किया गया था।

इसके अलावा आप भी एक निजी विधि में अभिव्यक्ति refactor सकता है:

private Expression<Func<Referral, bool>> Filter(string value) 
{ 
    return r => r.foo != null && 
       r.foo.bar != null && 
       r.foo.bar.baz != null && 
       r.foo.bar.baz.dummy == value; 
} 

और उसका उपयोग इस प्रकार है:

g => g.Count(Filter("Success")) 
9

आप निम्न विस्तार तरीकों का उपयोग कर सकते हैं।

public static TResult With<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator) 
    where TResult : class 
    where TInput : class 
{ 
    return o == null ? null : evaluator(o); 
} 

public static TResult Return<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator, TResult failureValue) 
    where TInput : class 
{ 
    return o == null ? failureValue : evaluator(o); 
} 

उनका संयोजन आप nulls से निपटने के लिए एक अच्छा, पठनीय एपीआई देता है:

return foo 
    .With(o => o.bar) 
    .With(o => o.baz) 
    .Return(o => o.dummy, null); 
+4

हालांकि यह सामान्य रूप से एक अच्छा विचार है, यह 'IQueryable' के साथ अच्छी तरह से नहीं चलता है। LINQ यह समझ नहीं पाएगा और thuis डेटाबेस पर बजाय क्लाइंट पर क्वेरी निष्पादित करता है। – Georg

+0

@Georg LINQ प्रदाताओं के साथ जो SQL में अनुवाद करते हैं, आप आमतौर पर केवल 'foo.bar.baz.dummy' लिख सकते हैं और कोई' NullReferenceException' नहीं प्राप्त कर सकते हैं, इसलिए आपको इस 'साथ' सहायक की आवश्यकता नहीं होगी। – hvd

+0

@hvd हां, क्योंकि आप आम तौर पर डेटाबेस स्तर पर सेट कर सकते हैं कि एनयूएल मानों को प्रचारित किया जाना चाहिए और यह भी डिफ़ॉल्ट व्यवहार है। हालांकि, यह बेहतर है कि समझने की आवश्यकता नहीं है कि आपको कौन सा डेटा स्रोत मिलेगा। – Georg

2

समस्या यह है कि ToDictionary विधि वास्तव में queryable पर नहीं किया जाता है - इसके बजाय, आप पूरे संग्रह प्राप्त , और डीबी सर्वर की बजाय अपने आवेदन में एकत्रीकरण करें। ToDictionary सीधे का उपयोग करने का

बजाय, का उपयोग Select पहले:

IQueryable<IGrouping<string, Referral>> queryable= ...; 
var dict = queryable.Select(g => new { Key = g.Key.ToString(), 
           Count = g.Count(r => r.foo.bar.baz.dummy == "Success") }) 
        .ToDictionary(i => i.Key, i => i.Count); 

इस एकत्रीकरण सी # कोड में डेटाबेस (जहां आप उन nulls के बारे में परवाह नहीं है) में किया जाता है और नहीं यकीन है कि कर देगा (जहां आपको NullReferenceException मिलता है)।

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

-1
// if null, use null 
if(objectvariable == null) 
{ 
// throw exception 
} 

// if not null 
if(objectvariable != null) 
{ 
// continue 
} 
संबंधित मुद्दे