2012-01-31 20 views
6

सामान्य परिस्थितियों में, एफ # कार्यों को new DelegateType पर कॉल करके और कार्य में एक तर्क के रूप में गुजरकर प्रतिनिधियों में परिवर्तित किया जा सकता है। लेकिन जब प्रतिनिधि में byref पैरामीटर होता है, तो यह सीधे संभव नहीं है। उदाहरण के लिए कोड:बाईफ के साथ कोई फ़ंक्शन सीधे प्रतिनिधि को क्यों परिवर्तित नहीं किया जा सकता है?

type ActionByRef<'a> = delegate of 'a byref -> unit 

let f (x:double byref) = 
    x <- 6.0 

let x = ref 42.0 
let d = new ActionByRef<_>(f) 

संकलन, तो निम्न त्रुटि दे रही है नहीं होगा:

This function value is being used to construct a delegate type whose signature includes a byref argument. You must use an explicit lambda expression taking 1 arguments.

let d = new ActionByRef<_>(fun x -> f(&x)) 

काम करता है का उपयोग करने के कोड को संशोधित करने, त्रुटि के बाद। लेकिन मेरा सवाल है: यह क्यों जरूरी है? एफ # नामित फ़ंक्शन से इस प्रतिनिधि को रूपांतरण क्यों नहीं देगा, लेकिन लैम्ब्डा से रूपांतरण ठीक है?

another question पर शोध करते समय मैं इस व्यवहार पर आया था। मुझे एहसास है कि byref केवल अन्य नेट भाषाओं के साथ संगतता के लिए है।

उत्तर

10

मुझे लगता है कि समस्या यह है कि byref<'T> F # में वास्तविक प्रकार नहीं है - यह एक प्रकार की तरह दिखता है (भाषा को सरल बनाने के लिए), लेकिन यह out ध्वज के साथ चिह्नित पैरामीटर में संकलित हो जाता है। इसका मतलब है कि byref<'T> केवल उस स्थान पर उपयोग किया जा सकता है जहां कंपाइलर वास्तव में out ध्वज का उपयोग कर सकता है।

फ़ंक्शन मानों के साथ समस्या यह है कि आप फ़ंक्शन बना सकते हैं उदा। आंशिक आवेदन के द्वारा:

let foo (n:int) (b:byref<int>) = 
    b <- n 

जब आप एक प्रतिनिधि के निर्माता के लिए एक तर्क के रूप foo गुजरती हैं, यह आंशिक आवेदन की एक विशिष्ट मामला है (कोई तर्क के साथ), लेकिन आंशिक आवेदन वास्तव में एक नई विधि का निर्माण और उसके बाद देने के लिए की जरूरत है कि प्रतिनिधि के लिए:

type IntRefAction = delegate of byref<int> -> unit 

let ac = IntRefAction(foo 5) 

संकलक चालाक हो सकता है और byref पैरामीटर (या out ध्वज) के साथ नई विधि पैदा करते हैं और उसके बाद से पारित है कि वास्तविक समारोह के संदर्भ द्वारा, लेकिन सामान्य रूप में, वहाँ अन्य compiler- हो जाएगा सकता है जेनरेट विधि जब आपका उपयोग नहीं करते हैंवाक्यविन्यास। इसे संभालने से जटिलता बढ़ेगी और मुझे लगता है कि यह अपेक्षाकृत दुर्लभ मामला है, इसलिए एफ # कंपाइलर ऐसा नहीं करता है और आपको अधिक स्पष्ट होने के लिए कहता है ...

+0

दिलचस्प, मैंने इसके बारे में नहीं सोचा था। एक नाइटपिक, मुझे लगता है कि 'byref'' ref' की तरह है, न कि 'बाहर'। – svick

+0

@ एसविक - आप सही हैं - असल में, आईएल स्तर पर, ध्वज 'रेफरी' है और सी # 'आउट 'बिल्कुल मौजूद नहीं है ... –

+0

दाएं, सी # का' आउट' वास्तव में' रेफरी 'प्लस है 'System.Runtime.InteropServices.Out' विशेषता। – ildjarn

संबंधित मुद्दे