सभी डिज़ाइन प्रक्रियाओं के परिणामस्वरूप पारस्परिक असंगत लक्ष्यों के बीच समझौता होता है। दुर्भाग्य से, &&
C ++ में ओवरलोड ऑपरेटर के लिए डिज़ाइन प्रक्रिया ने एक भ्रामक अंतिम परिणाम उत्पन्न किया: जो कि आप जिस सुविधा से चाहते हैं &&
- उसका लघु-परिचायक व्यवहार - छोड़ा गया है।
इस दुर्भाग्यपूर्ण जगह पर उस डिजाइन प्रक्रिया का विवरण कैसे समाप्त हुआ, यह मैं नहीं जानता। हालांकि यह देखना प्रासंगिक है कि बाद की डिजाइन प्रक्रिया ने इस अप्रिय परिणाम को कैसे ध्यान में रखा। सी # में, अतिभारित &&
ऑपरेटर है लघु सर्किटिंग। C # के डिजाइनरों ने कैसे हासिल किया?
अन्य उत्तरों में से एक "लंबोदर उठाने" का सुझाव देता है। अर्थात्:
A && B
नैतिक रूप से कुछ के रूप में महसूस किया जा सकता है:
operator_&& ( A, ()=> B )
जहाँ दूसरा तर्क आलसी मूल्यांकन के लिए कुछ तंत्र का उपयोग करता है ताकि मूल्यांकन करते समय, अभिव्यक्ति के दुष्प्रभाव और मूल्य उत्पन्न हों। अतिभारित ऑपरेटर के कार्यान्वयन केवल आवश्यक होने पर आलसी मूल्यांकन करेंगे।
यह वह नहीं है जो C # डिज़ाइन टीम ने किया था। (एक तरफ: हालांकि लैम्ब्डा लिफ्टिंग वह है जो मैंने तब किया था जब ऑपरेटर की अभिव्यक्ति ट्री प्रतिनिधित्व करने का समय आ गया था ??
, जिसे कुछ रूपांतरण कार्यों को आलसी तरीके से करने की आवश्यकता होती है। यह बताते हुए कि विस्तार में हालांकि एक बड़ा विषयांतर होगा। कहने के लिए पर्याप्त है कि लैम्ब्डा लिफ्टिंग। काम करता है लेकिन पर्याप्त रूप से भारी है कि हम इसे टालना चाहते हैं।)
बल्कि, सी # समाधान समस्या को दो अलग-अलग समस्याओं में तोड़ देता है:
- क्या हमें दाहिने हाथ के ऑपरेंड का मूल्यांकन करना चाहिए?
- यदि उपरोक्त का उत्तर "हां" था, तो हम दोनों ऑपरेंड को कैसे जोड़ेंगे?
इसलिए समस्या को &&
सीधे ओवरलोड करने के लिए अवैध बनाकर हल किया जाता है। बल्कि, C # में आपको दो ऑपरेटरों को ओवरलोड करना होगा , जिनमें से प्रत्येक उन दो प्रश्नों में से एक का उत्तर देता है।
class C
{
// Is this thing "false-ish"? If yes, we can skip computing the right
// hand size of an &&
public static bool operator false (C c) { whatever }
// If we didn't skip the RHS, how do we combine them?
public static C operator & (C left, C right) { whatever }
...
(एक तरफ: वास्तव में, तीन। सी # की आवश्यकता है कि यदि ऑपरेटर false
प्रदान किया जाता है तो ऑपरेटर true
को भी प्रदान किया जाना चाहिए, जो प्रश्न का उत्तर देता है: क्या यह बात "सच-ईश है?"। आमतौर पर केवल एक ही ऐसे ऑपरेटर को उपलब्ध कराने का कोई कारण नहीं होगा # सी। दोनों की आवश्यकता है।)
फार्म के एक विवरण पर विचार करें:
C cresult = cleft && cright;
कंपाइलर इसके लिए कोड बनाता है जैसा आपने सोचा था कि आपने यह छद्म सी # लिखा था:
C cresult;
C tempLeft = cleft;
cresult = C.false(tempLeft) ? tempLeft : C.&(tempLeft, cright);
जैसा कि आप देख सकते हैं, बाएं हाथ की ओर हमेशा मूल्यांकन किया जाता है। यदि यह "असत्य-ईश" होना निर्धारित है तो यह परिणाम है। अन्यथा, दाहिने हाथ की ओर का मूल्यांकन किया जाता है, और उत्सुक उपयोगकर्ता-परिभाषित ऑपरेटर &
को आमंत्रित किया जाता है।
||
ऑपरेटर ऑपरेटर की एक मंगलाचरण सच्चे और उत्सुक के रूप में, अनुरूप तरह से परिभाषित किया गया है |
ऑपरेटर:
cresult = C.true(tempLeft) ? tempLeft : C.|(tempLeft , cright);
सभी चार ऑपरेटरों को परिभाषित करके - true
, false
, &
और |
- सी # आप न केवल कहने के लिए अनुमति देता है cleft && cright
, लेकिन यह भी गैर शॉर्ट सर्किट cleft & cright
, और यह भी if (cleft) if (cright) ...
, और c ? consequence : alternative
और while(c)
, और इतने पर।
अब, मैंने कहा कि सभी डिजाइन प्रक्रियाएं समझौता का परिणाम हैं। यहां C # भाषा डिजाइनर शॉर्ट-सर्कुलेटिंग &&
और ||
राइट प्राप्त करने में कामयाब रहे , लेकिन ऐसा करने के लिए दो के बजाय चार ऑपरेटरों को ओवरलोड करने की आवश्यकता होती है , जो कुछ लोग भ्रमित करते हैं। ऑपरेटर सही / गलत सुविधा C # में कम से कम अच्छी तरह से समझी जाने वाली सुविधाओं में से एक है। एक समझदार और सीधी भाषा होने का लक्ष्य जो C ++ उपयोगकर्ताओं के लिए परिचित है, इच्छाओं का विरोध कम सर्कुलेटिंग और लैम्ब्डा उठाने या आलसी मूल्यांकन के अन्य रूपों को लागू नहीं करने की इच्छा से किया गया था। मुझे लगता है कि एक उचित समझौता स्थिति थी, लेकिन यह महसूस करने के लिए यह महत्वपूर्ण है कि है एक समझौता स्थिति। बस एक अलग है C ++ के डिजाइनरों से समझौता स्थिति।
यदि ऐसे ऑपरेटरों के लिए भाषा डिज़ाइन का विषय आपको पसंद है, तो मेरी श्रृंखला को पढ़ने पर विचार करें क्यों C # इन ऑपरेटरों को अशक्त मल पर परिभाषित नहीं करता है:
http://ericlippert.com/2012/03/26/null-is-not-false-part-one/
operator&&(const Foo& lhs, const Foo& rhs) : (lhs.bars == 0)