c# - नल कोलेसिंग ऑपरेटर का उपयोग करने के अनोखे तरीके




coding-style null (10)

मुझे पता है कि सी # में नल कोलेसिंग ऑपरेटर का उपयोग करने का मानक तरीका डिफ़ॉल्ट मान सेट करना है।

string nobody = null;
string somebody = "Bob Saget";
string anybody = "";

anybody = nobody   ?? "Mr. T"; // returns Mr. T
anybody = somebody ?? "Mr. T"; // returns "Bob Saget"

लेकिन और क्या कर सकते हैं ?? प्रयोग किया जाता है? यह अधिक संक्षिप्त और पढ़ने के लिए आसान होने के अलावा, टर्नरी ऑपरेटर के रूप में उपयोगी प्रतीत नहीं होता है:

nobody = null;
anybody = nobody == null ? "Bob Saget" : nobody; // returns Bob Saget

तो यह देखते हुए कि कम कोलेरिंग ऑपरेटर के बारे में भी कम पता है ...

  • क्या आपने इस्तेमाल किया है ?? कुछ और के लिए?

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


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

असल में, मेरा अनुभव यह है कि बहुत कम लोग टर्नरी ऑपरेटर से परिचित हैं (या अधिक सही ढंग से, सशर्त ऑपरेटर; ?: "टर्नरी" एक ही अर्थ में है कि || बाइनरी है या + या तो यूनरी या बाइनरी है; यह करता है हालांकि कई भाषाओं में एकमात्र टर्नरी ऑपरेटर होता है), इसलिए कम से कम उस सीमित नमूने में, आपका कथन वहां विफल रहता है।

इसके अलावा, जैसा कि पहले उल्लेख किया गया है, वहां एक बड़ी स्थिति है जब नल कोलेसिंग ऑपरेटर बहुत उपयोगी होता है, और जब भी अभिव्यक्ति का मूल्यांकन किया जाता है तो इसका कोई दुष्प्रभाव होता है। उस स्थिति में, आप सशर्त ऑपरेटर का उपयोग नहीं कर सकते हैं (ए) अस्थायी परिवर्तनीय पेश करना, या (बी) आवेदन के वास्तविक तर्क को बदलना। (बी) किसी भी परिस्थिति में स्पष्ट रूप से उचित नहीं है, और जब यह व्यक्तिगत वरीयता है, तो मुझे बहुत से अपर्याप्त के साथ घोषणा के दायरे को अपनाना पसंद नहीं है, भले ही अल्पकालिक, चर, तो (ए) उसमें भी बाहर है विशेष परिदृश्य

बेशक, यदि आपको परिणाम पर एकाधिक चेक करने की आवश्यकता है, तो सशर्त ऑपरेटर, या ब्लॉक के सेट, शायद नौकरी के लिए उपकरण हैं। लेकिन सरल के लिए "अगर यह शून्य है, तो इसका इस्तेमाल करें, अन्यथा इसका उपयोग करें", नल कोलेसिंग ऑपरेटर ?? पूर्ण है।


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

आपको अपने इरादे को सबसे अच्छा व्यक्त करने का उपयोग करना चाहिए। चूंकि एक नल कोलेसे ऑपरेटर है, इसका इस्तेमाल करें

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


एक अजीब उपयोग के मामले की बिट, लेकिन मेरे पास एक तरीका था जहां एक IDisposable ऑब्जेक्ट संभावित रूप से एक तर्क के रूप में पारित किया जाता है (और इसलिए माता-पिता द्वारा निपटाया जाता है), लेकिन यह भी शून्य हो सकता है (और इसलिए स्थानीय विधि में बनाया और डिस्पोजेड किया जाना चाहिए)

इसका उपयोग करने के लिए, कोड या तो दिखता था

Channel channel;
Authentication authentication;

if (entities == null)
{
    using (entities = Entities.GetEntities())
    {
        channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
        [...]
    }
}
else
{
    channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
    [...]
}

लेकिन एक नल coalesce के साथ बहुत neater हो जाता है

using (entities ?? Entities.GetEntities())
{
    channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
    [...]
}

एक और फायदा यह है कि टर्नरी ऑपरेटर को दोहरे मूल्यांकन या अस्थायी चर की आवश्यकता होती है।

उदाहरण के लिए, इस पर विचार करें:

string result = MyMethod() ?? "default value";

जबकि टर्नरी ऑपरेटर के साथ आप या तो छोड़ दिया जाता है:

string result = (MyMethod () != null ? MyMethod () : "default value");

जो MyMethod को दो बार कॉल करता है, या:

string methodResult = MyMethod ();
string result = (methodResult != null ? methodResult : "default value");

किसी भी तरह से, नल कोलेसिंग ऑपरेटर क्लीनर है और, मुझे लगता है, अधिक कुशल।


केवल समस्या यह है कि नल-कोलेसे ऑपरेटर खाली तारों का पता नहीं लगाता है।

अर्थात

string result1 = string.empty ?? "dead code!";

string result2 = null ?? "coalesced!";

उत्पादन:

result1 = ""

result2 = coalesced!

मैं वर्तमान में ओवरराइडिंग में देख रहा हूँ ?? इस के आसपास काम करने के लिए ऑपरेटर। यह फ्रेमवर्क में बनाया गया यह सुनिश्चित करने के लिए आसान होगा।

विचार?


खैर, सबसे पहले, मानक टर्नरी की तुलना में श्रृंखला के लिए यह बहुत आसान है:

string anybody = parm1 ?? localDefault ?? globalDefault;

बनाम

string anyboby = (parm1 != null) ? parm1 
               : ((localDefault != null) ? localDefault 
               : globalDefault);

यदि नल-संभावित ऑब्जेक्ट एक चर नहीं है तो यह भी अच्छी तरह से काम करता है:

string anybody = Parameters["Name"] 
              ?? Settings["Name"] 
              ?? GlobalSetting["Name"];

बनाम

string anybody = (Parameters["Name"] != null ? Parameters["Name"] 
                 : (Settings["Name"] != null) ? Settings["Name"]
                 :  GlobalSetting["Name"];

मैं नल coalesce ऑपरेटर आलसी लोड कुछ गुणों के लिए उपयोग करना पसंद है।

मेरे बिंदु को स्पष्ट करने के लिए बस एक बहुत ही सरल (और contrved) उदाहरण:

public class 
{
    private IEnumerable<string> _definitions;
    public IEnumerable<string> Definitions
    {
        get
        {
            return _definitions ?? (
                _definitions = new List<string>
                {
                    "definition 1",
                    "definition 2",
                    "definition 3"
                }
            );
        }
    } 
}

मैंने इसे आलसी लोड एक-लाइनर के रूप में उपयोग किया है:

public MyClass LazyProp
{
    get { return lazyField ?? (lazyField = new MyClass()); }
}

पठनीय? अपने लिए तय करें।


मैंने उपयोग किया है ?? IDataErrorInfo के कार्यान्वयन में:

public string Error
{
    get
    {
        return this["Name"] ?? this["Address"] ?? this["Phone"];
    }
}

public string this[string columnName]
{
    get { ... }
}

यदि कोई व्यक्तिगत संपत्ति "त्रुटि" स्थिति में है तो मुझे वह त्रुटि मिलती है, अन्यथा मैं शून्य हो जाता हूं। वास्तव में अच्छी तरह से काम करता है।


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

ऐसे में ऐसे परिदृश्य हैं जहां आपको टर्नरी का उपयोग नहीं करना चाहिए, उदाहरण के लिए:

public class A
{
    var count = 0;
    private int? _prop = null;
    public int? Prop
    {
        get 
        {
            ++count;
            return _prop
        }
        set
        {
            _prop = value;
        }
    }
}

यदि तुम प्रयोग करते हो:

var a = new A();
var b = a.Prop == null ? 0 : a.Prop;

गेटर को दो बार बुलाया जाएगा और count चर 2 के बराबर होगा, और यदि आप इसका उपयोग करते हैं:

var b = a.Prop ?? 0

count चर 1 के बराबर होगा, जैसा कि इसे करना चाहिए।





null-coalescing-operator