बूलियन अभिव्यक्तियों में अशक्त सशर्त ऑपरेटरों का उपयोग करने का इष्टतम तरीका


11

आप एक बूलियन अभिव्यक्ति लिख रहे हैं जो इस तरह दिख सकती है:

team.Category == "A Team" && team?.Manager?.IsVietnamVet

public class Manager
{
    public bool IsVietnamVet { get; set; }
}

public class Team
{
    public string Category { get; set; }

    public Manager Manager { get; set; }
}

... और आपको एक त्रुटि मिलती है:

ऑपरेटर '&&' प्रकार 'बूल' और 'बूल' के ऑपरेंड पर लागू नहीं किया जा सकता है

इसे संभालने के लिए इष्टतम / सबसे साफ तरीका क्या है?

  1. team.Category == "A Team" && (team?.Manager?.IsVietnamVet ?? false)

    क्या यह वास्तव में पठनीय है?

  2. team.Category == "A Team" && (team?.Manager?.IsVietnamVet).GetValueOrDefault()

    यह LINQ-to-Entities में काम नहीं कर सकता है ...

  3. team.Category == "A Team" && team?.Manager?.IsVietnamVet == true

    क्या आप वाकई if (condition == true)बिना किसी झिझक के लिखेंगे ?

क्या कोई अन्य विकल्प भी हैं? क्या अंततः लिखना बेहतर है:

  1. team.Category == "A Team" && team.Manager != null && team.Manager.IsVietnamVet

अगर ((String.IsNullOrEmpty (team.Manager) और& कंडीशन)) ...
स्नूप

1
@StevieV शुरू से ही इस अधिकार की तरह था;)
संथोस

1
कोड को अधिक ध्यान से देखने पर, अशक्त सशर्त भाग होना चाहिए team.Manager?.IsVietnamVet, अर्थात बाद में कोई अशक्त स्थिति नहीं है team, क्योंकि पहले से ही नहीं हो सकता है null
स्विक

2
"क्या तुम सच में लिखोगे अगर (शर्त == सच) बिना किसी झिझक के?" एक सामान्य बूलियन के लिए, नहीं, क्योंकि यह शानदार है। हालांकि, एक अशक्त बूलियन के लिए , यह प्रासंगिक है। nullableBool == trueमूल रूप से परीक्षण कर रहा है nullableBool != false && nullableBool != null(और यह इसका दूसरा भाग है जो इसे उपयोगी बनाता है और इसलिए अति- उपयोगी नहीं है)
Flater

2
nullableBool == trueयदि मैंने रैपर नहीं बनाया तो मैंने उपयोग करना शुरू कर दिया । यह पठनीय है क्योंकि आप सामान्य == trueरूप से @Fater उल्लेख के रूप में नियमित बूलियन का उपयोग करते समय नहीं लिखते हैं , इसलिए यह सुझाव देता है कि चर अशक्त है। अंततः, यह LINQ पठनीयता में सुधार करता है क्योंकि आप @Fabio उल्लेखों के रूप में कई अशक्त स्थितियों का उपयोग नहीं करते हैं।
संथोस

जवाबों:


4

इस विशेष मामले में, यह बुद्धिमान पालन करने के लिए हो सकता है Demeter के कानून यानी

public class Team
{
    public bool IsManagerVietnamVet => Manager?.IsVietnamVet ?? false;
}    

आम तौर पर, यदि बूलियन अभिव्यक्ति जटिल या बदसूरत है, तो यह कहने के लिए कुछ भी नहीं है कि आप इसे (या इसका हिस्सा) एक अलग बयान में विभाजित नहीं कर सकते हैं:

bool isVietnamVet = Manager?.IsVietnamVet ?? false;

if (team.Category == "A Team" && isVietnamVet)

जब डिबगर में कोड के माध्यम से कदम रखते हैं, तो अक्सर यह अच्छा होता है कि boolमाउसओवर-होवरिंग का एक छोटा सा हिस्सा बचाने के लिए बस एक ही में पैक की गई स्थिति ; वास्तव में, यह पूरी तरह से एक boolचर में डाल करने के लिए अच्छा हो सकता है ।

bool isVietnamVetAndCategoryA = (team.Category == "A Team"
    && Manager?.IsVietnamVet ?? false);

if (isVietnamVetAndCategoryA)

या LINQ के साथ:

var wibble = from flight in airport
             from passenger in flight.manifest
             let isOnPlane = 
                 (flight.FinishedBoarding && passenger.Flight == flight.FlightNumber)
             where !isOnPlane
             select passenger;

मुझे लगता है कि मैं ज्यादातर इस तरह के समाधान की ओर झुक रहा हूं।
संथोस

1
नई सी # कुछ लाइनों को बचाने के लिए वाक्यविन्यास: सार्वजनिक बूल IsManagerVinosVet => (team.Category == "") और& (टीम। प्रबंधक (.IsVinosVet ?? false)?
ग्राहम

बस ध्यान रखें कि लंबे समय तक a && b && c &&...क्रमिक रूप से निष्पादित किया जाता है, और अगले वाले को भी निष्पादित नहीं किया जाता है यदि पिछले एक है false। इसलिए लोग आमतौर पर शुरुआत में सबसे तेजी से डालते हैं। एक अलग बूल-वार में सामान ले जाते समय इसे ध्यान में रखें
jitbit

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

@BenCottrell मैं इसे "माइक्रो" ऑप्टिमाइज़ेशन कहूंगा अगर IsManagerVietnamVetप्रॉपर्टी किसी डेटाबेस में जांच के लिए जाती है;)
jitbit

3

मुझे लगता है कि विकल्प 3 (यानी == true) यह परीक्षण करने का सबसे साफ तरीका bool?है true, क्योंकि यह इस बारे में बहुत स्पष्ट है कि यह क्या करता है।

अधिकांश कोड में x == trueइसका कोई मतलब नहीं है, क्योंकि यह वैसा ही है x, लेकिन यह यहां लागू नहीं होता है, इसलिए मुझे लगता है == trueकि यह बहुत भ्रामक नहीं होगा।


1
मुझे लगता है कि यह निश्चित रूप से जाने का रास्ता होगा यदि हम अशक्त सशर्त संचालक का उपयोग करना चाहते थे, क्योंकि यह भी सुरक्षित है। सवाल यह है कि क्या पठनीयता अच्छी है। मेरे दृष्टिकोण से, विकल्प ऑप्ट 3 और ऑप्ट 4 के बीच है और मैं पठनीयता के कारण 3 से अधिक 3 का चयन करूंगा, प्रोग्रामर का इरादा थोड़ा स्पष्ट है। मैंने बेन कॉटरेल के उत्तर को सही के रूप में चिह्नित किया है क्योंकि मुझे वह दृष्टिकोण थोड़ा अधिक पसंद है। अगर मैं दो उत्तरों को चिह्नित कर सकता हूं, तो मैं करूंगा।
सन्थोस

1
@ संथोस - री "प्रोग्रामर का इरादा थोड़ा स्पष्ट लगता है"। IMHO, यह एक ऐसा मामला है जहां पहली बार एक प्रोग्रामर देखता है कि a?.b == trueवे भ्रमित होंगे, लेकिन एक बार जब वे समझ लेते हैं कि यह क्या कर रहा है, तो यह एक बहुत ही पढ़ने योग्य मुहावरा बन जाता है, != nullएक जटिल अभिव्यक्ति के बीच में परीक्षण करने की तुलना में बहुत अच्छा है । उसी के लिए a?.b ?? false, जो सबसे लोकप्रिय समाधान के रूप में कर्षण प्राप्त कर चुका है, क्योंकि यह मेल खाता है कि आप क्या टाइप करेंगे यदि आप बूलियन के अलावा किसी अन्य प्रकार के साथ काम कर रहे थे [हालांकि मुझे यह बूलियन के लिए पसंद नहीं है; मेरे लिए, यह स्वाभाविक रूप से नहीं पढ़ता है; मैं पसंद करता हूं == true]।
टूलमेकरसैट

3

बेन कॉटरेल के जवाब पर विस्तार करते हुए, "नल ऑब्जेक्ट" पैटर्न आपको आगे मदद कर सकता है।

एक nullटीम / प्रबंधक को वापस करने के बजाय , निकालें ITeamऔर IManagerइंटरफेस और सार्थक वैकल्पिक कार्यान्वयन लौटाएं:

public class NoManager : IManager
{
    public bool IsVietnamVet => false;
}

public class NoTeam : ITeam
{
    public bool ManagedByVietnamVet => false;

    public IManager Manager => new NoManager();
}

फिर अचानक आप team.ManagedByVietnamVetसुरक्षित रूप से कर सकते हैं ।

यह निश्चित रूप से अपस्ट्रीम प्रदाता पर निर्भर करता है, जो teamअशक्त है - लेकिन यह उचित परीक्षण के साथ सुनिश्चित किया जा सकता है।


-4

मैंने लिखा एक साधारण वर्ग जिसका आप उपयोग कर सकते हैं:

 public class MyBool 
    {
        public bool? Value { get; set; }

        public MyBool(bool b)
        {
            Value = b;
        }

        public MyBool(bool? b)
        {
            Value = b;
        }

        public static implicit operator bool(MyBool m)
        {
            return m?.Value ?? false;
        }

        public static implicit operator bool?(MyBool m)
        {
            return m?.Value;
        }

        public static implicit operator MyBool(bool m)
        {
            return new MyBool(m);
        }

        public static implicit operator MyBool(bool? m)
        {
            return new MyBool(m);
        }

        public override string ToString()
        {
            return Value.ToString();
        }
    }

यदि एक कस्टम प्रकार का उपयोग करने के लिए विश्वसनीय है, तो निश्चित रूप से। आप MyBoolदोनों के साथ तुलना कर सकते हैं boolऔर Nullable<bool>


1
यह साइट सॉफ़्टवेयर डिज़ाइन के बारे में प्रश्नों के लिए है कि कैसे काम करने के लिए कोड के विशिष्ट टुकड़े प्राप्त करें, इसलिए यदि आपको लगता है कि यह सबसे अच्छा समाधान है, तो आपका जवाब इस बात पर ध्यान केंद्रित करना चाहिए कि आप इस तरह से एक वर्ग को क्यों मानते हैं, यह सर्वोत्तम संभव समाधान है, न कि इसे लागू करने के लिए सटीक कोड की आवश्यकता है।
Ixrec
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.