सशर्त का उपयोग करने के लाभ ?: (टर्नरी) ऑपरेटर


101

के लाभ और कमियां क्या हैं ?: ऑपरेटर मानक के विपरीत अगर-और कथन। स्पष्ट लोगों को:

सशर्त ?: ऑपरेटर

  • प्रत्यक्ष मूल्य तुलना और असाइनमेंट के साथ काम करते समय छोटा और अधिक संक्षिप्त
  • के रूप में अगर / अन्यथा निर्माण के रूप में लचीला नहीं लगता है

स्टैंडर्ड इफ / एल्स

  • अधिक स्थितियों पर लागू किया जा सकता है (जैसे फ़ंक्शन कॉल)
  • अक्सर अनावश्यक रूप से लंबे होते हैं

पठनीयता कथन के आधार पर प्रत्येक के लिए भिन्न प्रतीत होती है। पहली बार उजागर होने के बाद थोड़ी देर के लिए ?: ऑपरेटर, मुझे यह पचाने में कुछ समय लगा कि यह कैसे काम करता है। क्या आप इसे जहाँ भी संभव हो, उपयोग करने की सलाह देंगे या अगर मैं और भी कई गैर-प्रोग्रामर के साथ काम करूँ / तो रहूँ?


8
आप पहले से ही इसका सार मिल गया।
बायरन व्हिटलॉक

1
@ नाइकोलस नाइट: मैं अनुमान लगा रहा हूं कि ओपी का मतलब है कि आप ऐसा नहीं कर सकते हैं, जैसे, SomeCheck() ? DoFirstThing() : DoSecondThing();- आपको मूल्य वापस करने के लिए अभिव्यक्ति का उपयोग करना होगा।
दान ताओ

6
जहाँ यह स्पष्ट है उसका उपयोग करें , अगर ऐसा नहीं है तो / साथ रहें। कोड स्पष्टता आपका मुख्य विचार होना चाहिए।
होल्स्क

8
दिखाई दिया '??' अभी तक? गंभीरता से, अगर आपको लगता है ternaries हैं शांत ...
PDR

3
+1 इसे केवल "टर्नरी ऑपरेटर" के रूप में न कहने के लिए। भले ही यह C # में एक ही टर्नरी (यूनिरी और बाइनरी के विपरीत) ऑपरेटर है, लेकिन यह इसका नाम नहीं है।
जॉन एम गैंट जूल

जवाबों:


122

मैं मूल रूप से केवल इसका उपयोग करने की सिफारिश करूंगा जब परिणामी बयान बेहद छोटा हो और पठनीयता का त्याग किए बिना अगर / और समकक्ष पर सहमति में महत्वपूर्ण वृद्धि का प्रतिनिधित्व करता है।

अच्छा उदाहरण:

int result = Check() ? 1 : 0;

खराब उदाहरण:

int result = FirstCheck() ? 1 : SecondCheck() ? 1 : ThirdCheck() ? 1 : 0;

5
अच्छी कॉल, लेकिन रिकॉर्ड के लिए, यह "सहमति" है।
mqp

6
@ mquander, क्या आप इसके बारे में निश्चित हैं? merriam-webster.com/dEDIA/concise
बायरन

39
मैं हमेशा एक सरल के साथ शुरू करता हूं और समय के साथ इसे और अधिक जटिल बनाता हूं जब तक कि यह पूरी तरह से अपठनीय न हो।
ज्यूके वैन डेर मास

9
दूसरे उदाहरण में पठनीयता को बेहतर प्रारूपण के साथ आसानी से सुधारा जा सकता है। लेकिन, जैसा कि ओपी सिफारिश कर रहा है, यह पठनीयता और वर्सोसिटी बनाम वर्बोसिटी के लिए नीचे आता है।
नाथन अर्नस्ट

4
ओपी के सवाल का हिस्सा नहीं है, लेकिन ध्यान रखना महत्वपूर्ण है कि आप returnटर्नरी ऑपरेशन के परिणाम का हिस्सा नहीं हो सकते हैं । उदाहरण के लिए: check() ? return 1 : return 0;काम नहीं करेगा, लेकिन return check() ? 1 : 0;होगा। हमेशा प्रोग्रामिंग में इन छोटे quirks खोजने के लिए मजेदार।
CSS

50

यह अन्य उत्तरों द्वारा बहुत अधिक कवर किया गया है, लेकिन "यह एक अभिव्यक्ति है" वास्तव में यह नहीं समझाता है कि यह इतना उपयोगी क्यों है ...

C ++ और C # जैसी भाषाओं में, आप स्थानीय रेडीली फ़ील्ड्स (एक विधि निकाय के भीतर) का उपयोग करके उन्हें परिभाषित कर सकते हैं। यह एक पारंपरिक अगर / तो बयान के साथ संभव नहीं है क्योंकि एक एकल क्षेत्र के मूल्य को उस एकल विवरण के भीतर सौंपा जाना है:

readonly int speed = (shiftKeyDown) ? 10 : 1;

के रूप में ही नहीं है:

readonly int speed;  
if (shifKeyDown)  
    speed = 10;    // error - can't assign to a readonly
else  
    speed = 1;     // error  

इसी तरह आप अन्य कोड में तृतीयक अभिव्यक्ति एम्बेड कर सकते हैं। स्रोत कोड को अधिक कॉम्पैक्ट बनाने के साथ ही (और कुछ मामलों में परिणामस्वरूप अधिक पठनीय) यह उत्पन्न मशीन कोड को और अधिक कॉम्पैक्ट और कुशल बना सकता है:

MoveCar((shiftKeyDown) ? 10 : 1);

... एक ही विधि को दो बार कॉल करने की तुलना में कम कोड उत्पन्न कर सकते हैं:

if (shiftKeyDown)
    MoveCar(10);
else
    MoveCar(1);

बेशक, यह एक और अधिक सुविधाजनक और संक्षिप्त रूप है (कम टाइपिंग, कम पुनरावृत्ति, और यदि आप एक / अन्य तरीके से कोड के डुप्लिकेट को कॉपी करना है तो त्रुटियों की संभावना को कम कर सकते हैं)। स्वच्छ "सामान्य पैटर्न" में इस तरह के मामले:

object thing = (reference == null) ? null : reference.Thing;

... इसे पढ़ने / पार्स / समझने (एक बार जब आप इसके लिए उपयोग किया जाता है) की तुलना में तेजी से लंबे समय से घुमावदार हैं यदि / और इसके बराबर है, तो यह आपको तेजी से 'ग्रॉक' कोड में मदद कर सकता है।

बेशक, सिर्फ इसलिए कि यह उपयोगी है इसका मतलब यह नहीं है कि यह हर मामले में उपयोग करने के लिए सबसे अच्छी बात है । मैं केवल कोड के छोटे बिट्स के लिए इसका उपयोग करने की सलाह दूंगा जहां अर्थ स्पष्ट है (या अधिक स्पष्ट किया गया है) का उपयोग करके ?:- यदि आप इसे अधिक जटिल कोड में उपयोग करते हैं, या एक दूसरे के भीतर घोंसले के संचालनकर्ता इसे कोड को पढ़ने के लिए बहुत मुश्किल बना सकते हैं ।


@ जामिन ग्रे "का मतलब यह नहीं है कि, जब स्थिरांक बनाया जाता है, तो यह 10 या 1. पर सेट होता है" क्या आपका मतलब यह है कि इसका मतलब है? गलत टिप्पणियाँ नए C ++ प्रोग्रामर को उस समस्या से अधिक भ्रम पैदा कर सकती हैं, जिस मुद्दे को आप दूर करने का प्रयास कर रहे थे;)
क्लॉन्क्सेक्स

5
इसके पार आने वाले भविष्य के पाठकों के लिए, " const int speed = (shiftKeyDown); 10: 1? ", इसका मतलब है कि जब स्थिरांक पहली बार बनाया जाता है , तो यह 10 या 1 पर सेट होता है। इसका मतलब यह नहीं है कि हर बार कंटिन्यू एक्सेस किया गया है यह एक चेक करता है। (बस एक नया सी ++ प्रोग्रामर उलझन में था)
जामिन ग्रे

2
... या इसे किसी अन्य तरीके से रखने के लिए, एक constस्थिर है, अर्थात इसे उस बयान के बाद नहीं बदला जा सकता है जिसमें यह घोषित किया गया है।
जेसन विलियम्स

1
@JaminGrey। readonlyहालांकि यह नहीं होना चाहिए ? मुझे हमेशा से लगता constथा कि " संकलन के समय हल किया जाता था और जहां भी उपयोग किया जाता है, वहां लाइन में खड़ा होता है "।
नोलोनार

1
@ColinWiseman, यह उदाहरण के लिए एक उदाहरण है ?: का उपयोग किया जा सकता है। मैं विशेष रूप से बताता हूं कि सिर्फ इसलिए कि आप इसे कर सकते हैं, इसका मतलब यह नहीं है कि यह किसी भी विशिष्ट मामले में करने के लिए जरूरी "सबसे अच्छा" है। उस काम को करने के लिए, पाठक से अपेक्षा की जाती है कि वे अपने मस्तिष्क का उपयोग हर बार एक ऐसे मामले में करें जहाँ यह उनके लिए उपयोगी हो।
जेसन विलियम्स

14

मैं आमतौर पर एक टर्नरी ऑपरेटर का चयन करता हूं जब मेरे पास बहुत सारे डुप्लिकेट कोड होंगे अन्यथा।

if (a > 0)
    answer = compute(a, b, c, d, e);
else
    answer = compute(-a, b, c, d, e);

एक टर्नरी ऑपरेटर के साथ, यह निम्नलिखित के साथ पूरा किया जा सकता है।

answer = compute(a > 0 ? a : -a, b, c, d, e); 

12
व्यक्तिगत रूप से मैं क्या करना होगा aVal = a > 0 ? a : -a; answer = compute(aVal,b,c,d,e);खास तौर पर अगर b, c, dऔर eभी आवश्यक उपचार।
corsiKa

10
इस उदाहरण में एक सशर्त का उपयोग क्यों करें? बस एक बार ABS (a) और कॉल कंप्यूट () प्राप्त करें।
ऐश

2
हाँ, मैंने सबसे अच्छा उदाहरण नहीं बनाया। :)
रयान ब्राइट

एक नौसिखिया के लिए, यह समकक्ष नहीं दिखता है। क्या इसका उत्तर देने की आवश्यकता नहीं है = गणना (a> 0; a, b, c, d, e: -a, b, c, d, e); ?
pbreitenbach

@pbreitenbach: नहीं - यह पूर्वता की बात है - पहला तर्क compute(...)है a > 0 ? a : -1, जिसका मूल्यांकन सभी अन्य अल्पविराम से अलग तर्क से किया जाता है। वैसे भी, दुर्भाग्य से C ++ में अल्पविराम से अलग किए गए मानों के "tuples" को संभालने के लिए आपके प्रश्न में संकेतन की कमी है, इसलिए यहां तक a > 0 ? (a, b, c, d, e) : (-a, b, c, d, e)कि अवैध भी है, और ऐसा कुछ भी नहीं है जो बिना बदलाव के computeही काम करता हो।
टोनी डेलरॉय

12

मुझे वेब डेवलपमेंट करते समय यह विशेष रूप से उपयोगी लगता है यदि मैं अनुरोध में भेजे गए मान को एक चर सेट करना चाहता हूं यदि यह परिभाषित नहीं है या कुछ डिफ़ॉल्ट मान नहीं है तो यह है।


3
वेब डिव में +1 डिफ़ॉल्ट मान एक उत्कृष्ट उदाहरण है जो टर्नरी ऑपरेटर का उपयोग करने के लिए एक अच्छी जगह है
बायरन व्हिटलोक

11

वास्तव में अच्छा उपयोग है:

x = foo ? 1 :
    bar ? 2 :
    baz ? 3 :
          4;

10
PHP में इससे सावधान रहें, टर्नरी ऑपरेटर PHP में गलत तरीके से जुड़ता है। अनिवार्य रूप से, यदि fooगलत है, तो पूरी चीज अन्य परीक्षण किए बिना 4 का मूल्यांकन करेगी।
टॉम बस्बी

4
@TomBusby - वाह। फिर भी PHP से नफरत करने का एक और कारण, यदि आप कोई है जो पहले से ही PHP से नफरत करता है।
टॉड लेहमन

6

सशर्त ऑपरेटर छोटी परिस्थितियों के लिए महान है, जैसे:

varA = boolB ? valC : valD;

मैं कभी-कभार इसका उपयोग करता हूं क्योंकि इस तरह से कुछ लिखने में कम समय लगता है ... दुर्भाग्य से, इस ब्रांचिंग को कभी-कभी किसी अन्य डेवलपर द्वारा अपने कोड को ब्राउज़ करके याद किया जा सकता है। इसके अलावा, कोड आमतौर पर इतना छोटा नहीं होता है, इसलिए मैं आमतौर पर डालकर पठनीयता में मदद करता हूं? और: अलग लाइनों पर, इस तरह:

doSomeStuffToSomething(shouldSomethingBeDone()
    ? getTheThingThatNeedsStuffDone()
    : getTheOtherThingThatNeedsStuffDone());

हालांकि, अगर / अन्यथा ब्लॉक (और मैं उन्हें क्यों पसंद करता हूं) का उपयोग करने का बड़ा फायदा यह है कि बाद में आना और शाखा में कुछ अतिरिक्त तर्क जोड़ना आसान है

if (shouldSomethingBeDone()) {
    doSomeStuffToSomething(getTheThingThatNeedsStuffDone());
    doSomeAdditionalStuff();
} else {
doSomeStuffToSomething(getTheOtherThingThatNeedsStuffDone());
}

या एक और शर्त जोड़ें:

if (shouldSomethingBeDone()) {
    doSomeStuffToSomething(getTheThingThatNeedsStuffDone());
    doSomeAdditionalStuff();
} else if (shouldThisOtherThingBeDone()){
    doSomeStuffToSomething(getTheOtherThingThatNeedsStuffDone());
}

तो, अंत में, यह आपके लिए सुविधा के बारे में है (बाद में उपयोग करने के लिए छोटा है?) बनाम आपके लिए सुविधा (और अन्य) बाद में। यह एक निर्णय कॉल है ... लेकिन अन्य सभी कोड-स्वरूपण मुद्दों की तरह, एकमात्र वास्तविक नियम सुसंगत होना है, और उन लोगों के लिए नेत्रहीन विनम्र होना है जिन्हें आपके कोड को बनाए रखना है (या ग्रेड!)।

(सभी कोड आंख संकलित)


5

टर्नेरी ऑपरेटर का उपयोग करते समय पहचानने वाली एक बात यह है कि यह एक अभिव्यक्ति है न कि एक बयान।

योजना की तरह कार्यात्मक भाषाओं में भेद मौजूद नहीं है:

(अगर (> अब) अब)

सशर्त ?: ऑपरेटर "के रूप में अगर / अन्यथा निर्माण के रूप में लचीला प्रतीत नहीं होता"

कार्यात्मक भाषाओं में यह है।

अनिवार्य भाषाओं में प्रोग्रामिंग करते समय मैं उन स्थितियों में टर्नरी ऑपरेटर को लागू करता हूं जहां मैं आमतौर पर अभिव्यक्ति (असाइनमेंट, सशर्त विवरण आदि) का उपयोग करता हूं।


5

हालांकि उपरोक्त उत्तर मान्य हैं, और मैं पठनीयता से सहमत होना महत्वपूर्ण है, पर विचार करने के लिए 2 और बिंदु हैं:

  1. C # 6 में, आपके पास अभिव्यक्ति-युक्त विधियाँ हो सकती हैं।

यह टर्नरी का उपयोग करने के लिए इसे विशेष रूप से संक्षिप्त बनाता है:

string GetDrink(DayOfWeek day) 
   => day == DayOfWeek.Friday
      ? "Beer" : "Tea";
  1. जब यह अंतर्निहित प्रकार रूपांतरण की बात आती है तो व्यवहार भिन्न होता है।

यदि आपके पास प्रकार हैं T1और T2दोनों को स्पष्ट रूप से परिवर्तित किया जा सकता है T, तो नीचे काम नहीं करता है:

T GetT() => true ? new T1() : new T2();

(क्योंकि संकलक त्रिगुट अभिव्यक्ति के प्रकार का निर्धारण करने की कोशिश करता है, और वहाँ के बीच कोई रूपांतरण नहीं है T1और T2।)

दूसरी ओर, if/elseनीचे दिया गया संस्करण काम करता है:

T GetT()
{
   if (true) return new T1();
   return new T2();
}

क्योंकि T1में परिवर्तित है Tऔर इसलिए हैT2


5

कभी-कभी यह पहली नज़र में पढ़ने के लिए एक बूल मूल्य का काम आसान बना सकता है:

// With
button.IsEnabled = someControl.HasError ? false : true;

// Without
button.IsEnabled = !someControl.HasError;

4

यदि मैं एक मान सेट कर रहा हूं और मुझे पता है कि ऐसा करने के लिए यह हमेशा एक पंक्ति का कोड होगा, तो मैं आमतौर पर टर्नरी (सशर्त) ऑपरेटर का उपयोग करता हूं। यदि भविष्य में मेरा कोड और लॉजिक बदल जाएगा, तो मैं अन्य प्रोग्रामरों के लिए अधिक स्पष्ट होने के साथ-साथ एक का उपयोग करता हूं।

आगे आप के लिए ब्याज हो सकता है ?? संचालक


4

सशर्त ऑपरेटर का लाभ यह है कि यह एक ऑपरेटर है। दूसरे शब्दों में, यह एक मूल्य लौटाता है। चूंकि ifएक बयान है, यह एक मूल्य वापस नहीं कर सकता है।


4

मैं टर्नरी के उपयोग को सीमित करने की सलाह दूंगा (:) :) ऑपरेटर को सरल सिंगल लाइन असाइनमेंट यदि / अन्यथा तर्क। कुछ इस पैटर्न जैसा दिखता है:

if(<boolCondition>) {
    <variable> = <value>;
}
else {
    <variable> = <anotherValue>;
}

आसानी से परिवर्तित किया जा सकता है:

<variable> = <boolCondition> ? <value> : <anotherValue>;

मैं उन स्थितियों में टर्नरी ऑपरेटर का उपयोग करने से बचना चाहिए जिनके लिए आवश्यकता होती है / if if / if, nested if / else, या if / else शाखा तर्क जिसके परिणामस्वरूप कई लाइनों का मूल्यांकन होता है। इन स्थितियों में टर्नेरी ऑपरेटर को लागू करने से अपठनीय, भ्रामक और असहनीय कोड का परिणाम होगा। उम्मीद है की यह मदद करेगा।


2

का उपयोग करने का कुछ प्रदर्शन लाभ है? संचालक उदा। MS Visual C ++, लेकिन यह वास्तव में एक संकलक विशिष्ट चीज है। संकलक वास्तव में कुछ मामलों में सशर्त शाखा का अनुकूलन कर सकता है।


2

परिदृश्य जो मैं खुद को सबसे अधिक उपयोग करता हूं वह डिफ़ॉल्ट मानों और विशेष रूप से रिटर्न में है

return someIndex < maxIndex ? someIndex : maxIndex;

वे वास्तव में एकमात्र ऐसी जगह हैं जहां मुझे यह अच्छा लगता है, लेकिन उनके लिए मैं करता हूं।

यद्यपि यदि आप एक बूलियन की तलाश कर रहे हैं तो यह कभी-कभी एक उपयुक्त चीज़ की तरह लग सकता है:

bool hey = whatever < whatever_else ? true : false;

क्योंकि पढ़ना और समझना इतना आसान है, लेकिन उस विचार को हमेशा अधिक स्पष्ट के लिए उछाला जाना चाहिए:

bool hey = (whatever < whatever_else);

2

यदि आपको एक ही स्थिति में कई शाखाओं की आवश्यकता है, तो एक का उपयोग करें:

if (A == 6)
  f(1, 2, 3);
else
  f(4, 5, 6);

यदि आपको विभिन्न स्थितियों के साथ कई शाखाओं की आवश्यकता है, तो यदि स्टेटमेंट काउंट स्नोबॉल होगा, तो आप टर्नरी का उपयोग करना चाहेंगे:

f( (A == 6)? 1: 4, (B == 6)? 2: 5, (C == 6)? 3: 6 );

इसके अलावा, आप प्रारंभ में टर्नरी ऑपरेटर का उपयोग कर सकते हैं।

const int i = (A == 6)? 1 : 4;

ऐसा करना अगर बहुत गन्दा है:

int i_temp;
if (A == 6)
   i_temp = 1;
else
   i_temp = 4;
const int i = i_temp;

आप इनिशियलाइज़ेशन को इफ़ / के अंदर नहीं रख सकते, क्योंकि यह स्कोप को बदल देता है। लेकिन संदर्भ और कांस्टेबल वैरिएबल केवल इनिशियलाइजेशन पर ही बाध्य हो सकते हैं।


2

टर्नरी ऑपरेटर को एक बार के भीतर शामिल किया जा सकता है, जबकि एक अगर-तब-और नहीं कर सकता है; दूसरी ओर, यदि एक-तब-तो लूप और अन्य कथनों को निष्पादित कर सकता है, जबकि टर्नरी ऑपरेटर केवल (संभवतः शून्य) प्रतिद्वंद्वियों को निष्पादित कर सकता है।

संबंधित नोट पर, && और || ऑपरेटर कुछ निष्पादन पैटर्न की अनुमति देते हैं, जो यदि-तब-तब लागू करना कठिन होता है। उदाहरण के लिए, यदि किसी के पास कॉल करने के लिए कई कार्य हैं और कोड का एक टुकड़ा निष्पादित करना चाहते हैं यदि उनमें से कोई भी विफल हो जाता है, तो इसे && ऑपरेटर का उपयोग करके अच्छी तरह से किया जा सकता है। उस ऑपरेटर के बिना ऐसा करना या तो अनावश्यक कोड, एक गोटो, या एक अतिरिक्त ध्वज चर की आवश्यकता होगी।


1

साथ सी # 7 , आप नए उपयोग कर सकते हैं रेफरी स्थानीय लोगों रेफरी संगत चर की सशर्त असाइनमेंट सरल करने के लिए शामिल हैं। तो अब, न केवल आप कर सकते हैं:

int i = 0;

T b = default(T), c = default(T);

// initialization of C#7 'ref-local' variable using a conditional r-value⁽¹⁾

ref T a = ref (i == 0 ? ref b : ref c);

... लेकिन यह भी बहुत अद्भुत:

// assignment of l-value⁽²⁾ conditioned by C#7 'ref-locals'

(i == 0 ? ref b : ref c) = a;

कोड की वह पंक्ति मान के आधार पर या aतो bया के मूल्य को निर्दिष्ट करती cहै i



नोट्स
1. आर-मूल्य है सही एक काम, मूल्य कि सौंप दिया जाता है की -hand ओर।
2. एल-वैल्यू एक असाइनमेंट के बाईं ओर स्थित है, चर जो असाइन किए गए मान को प्राप्त करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.