2012-01-18 11 views
11

न्यूनतम या अधिकतम दो संख्याओं/कार्यों की तुलना करते समय, सी # शॉर्ट सर्किट करता है यदि मामला पहले के लिए सच है और दूसरे के लिए सच बताएगा? इन मामलों में से विशिष्ट उदाहरणMath.Min या Math.Max ​​शॉर्ट-सर्किट की तुलना में तुलना करता है?

if(x < Math.Max(y, z())) 

और

if(x > Math.Min(y, z())) 

Math.Max(y, z()) के बाद से y के रूप में कम से कम के रूप में बड़े मान प्रदान करेगा, अगर एक्स < y फिर वहाँ z(), मूल्यांकन करने के लिए कोई जरूरत नहीं है जो कर रहे हैं थोड़ी देर लग सकता है Math.Min के साथ इसी तरह की स्थिति।

मुझे लगता है कि इन दोनों शॉर्ट सर्किट के लिए

if(x < y || x < z()) 

की तर्ज पर फिर से लिखा जा सकता है, लेकिन मुझे लगता है यह और अधिक स्पष्ट क्या तुलना पुनर्लेखन के बिना है। क्या यह शॉर्ट सर्किट है?

+3

मान लें कि आप 'if (x> XYZ (y, z()))' कंपाइलर XYZ के परिणाम को कैसे जानते हैं? अधिकतम, न्यूनतम, औसत या कुछ और? –

+0

@ एलबी महान बिंदु, मैंने इसे इस तरह से नहीं माना था। – yoozer8

+0

इसके अलावा, "लघु-सर्किट" अभिव्यक्ति बराबर नहीं हो सकती है, इस पर निर्भर करता है कि 'मिन' और' मैक्स 'नाइन कैसे संभालता है। – dan04

उत्तर

18

जैसा कि अन्य ने इंगित किया है, संकलक न्यूनतम या मैक्स के अर्थशास्त्र के बारे में कुछ भी नहीं जानता है, जो इस विधि को तोड़ने की अनुमति देगा कि विधि से पहले तर्कों का मूल्यांकन किया जाता है।

आप अपने खुद के लिखना चाहते थे, तो आप इतनी आसानी से पर्याप्त कर सकता है:

static bool LazyLessThan(int x, int y, Func<int> z) 
{ 
    return x < y || x < z(); 
} 

और फिर फोन यह

if (LazyLessThan(x, y, z)) 

या

if (LazyLessThan(x, y,()=>z())) 

या उस बात के लिए:

static bool LazyRelation<T>(T x, T y, Func<T> z, Func<T, T, bool> relation) 
{ 
    return relation(x, y) || relation(x, z()); 
} 
... 
if (LazyRelation(x, y,()=>z, (a,b)=> a < b))) 
+0

यह अंतिम उदाहरण बहुत अच्छा होगा, अगर डिफ़ॉल्ट तर्क जोड़ना संभव था, जैसे: स्थिर बूल LazyRelation (टी एक्स, टी वाई, Func एक्स, Func संबंध = (ए, बी) => ए <बी) – zmbq

+3

+1 ग्रेट उत्तर, लेकिन आइए ईमानदार रहें - क्या यह सब 'पढ़ने योग्य (x Yuck

+0

मैं कहूंगा कि यह कम पठनीय है, क्योंकि यह एक मूल मुहावरे को उस फ़ंक्शन के साथ बदल देता है जिसकी परिभाषा आपको कोड को समझने के लिए पढ़नी है। –

10

नहीं, यह शॉर्ट सर्किट नहीं करता है और जेड() का हमेशा मूल्यांकन किया जाएगा। यदि आप शॉर्ट सर्किटिंग व्यवहार चाहते हैं तो आपको फिर से लिखना चाहिए जैसा आपने किया है।

+4

इसका कारण यह है कि रनटाइम का यह जानने का कोई तरीका नहीं है कि 'अधिकतम() 'और' न्यूनतम() 'के प्रभाव क्या हैं। ** आप ** करते हैं, जो आपको अधिक प्रदर्शन करने के तरीके में फिर से लिखने की अनुमति देता है। – Yuck

2

नहीं, यह कम से कम सी # कंपाइलर स्तर पर शॉर्ट सर्किट नहीं करता है। Math.Min या Math.Max दो सामान्य स्थैतिक विधि कॉल हैं और संकलक उस अर्थ में अनुकूलित नहीं होंगे।

कोड हो जाएगा के मूल्यांकन के आदेश: जेड(), Math.Max, एक्स> ...

तुम सच में सुनिश्चित करने के लिए, आईएल कोड की जाँच करें।

5

Math.Min() और Math.Max() किसी अन्य की तरह विधियां हैं। उन्हें मूल्य वापस करने के लिए मूल्यांकन किया जाना चाहिए जो तुलना में दूसरे तर्क के रूप में उपयोग किया जाएगा। यदि आप शॉर्ट सर्किटिंग चाहते हैं तो आपको || ऑपरेटर का उपयोग करके स्थिति लिखनी होगी जैसा आपने दिखाया है।

3

(कुछ भी नहीं विशेष रूप से नए जोड़ने के लिए है, लेकिन मैं समझ मैं एक परीक्षण मैं इस पर चलते थे के परिणामों का हिस्सा चाहते हैं।)

Math.Max ​​() आसानी से CLR के जस्ट-इन-टाइम संकलक द्वारा inlined किया जा सकता है और वहां से मैं उत्सुक था कि क्या यह कोड को इस तरह से अनुकूलित कर सकता है कि यह शॉर्ट-सर्किट है।

तो मैंने एक माइक्रोबाइंचमार्क को मार दिया जो प्रत्येक अभिव्यक्ति का 1,000,000 बार मूल्यांकन करता है। z() के लिए, मैंने एक फ़ंक्शन का उपयोग किया जो रिकर्सिव विधि का उपयोग करके फाइब (15) की गणना करता है। क्योंकि यह (पता नहीं है और जांच नहीं करता,

x < Math.Max(y, z()) : 8097 ms 
x < y || x < z()  :  29 ms 

मैं CLR अनुमान लगा रहा हूँ कि किसी भी तरह से विधि से बचाता को क्रियान्वित करने से कॉल में कोड को बदलने नहीं देंगे: यहाँ दो चलाने का परिणाम हैं यह देखने के लिए कि क्या दिनचर्या का कोई दुष्प्रभाव होता है।