2012-08-24 13 views
6

एफ # 3.0 में सुरक्षित/आधार सदस्य उपयोग में परिवर्तन को समझना base और protected सदस्यों को कॉल के लिए कठोर चेक जोड़ता है। मेरे पास सी # में निम्नलिखित सार वर्ग की तरह कुछ है जिसमें व्युत्पन्न कक्षाओं द्वारा उपयोग किए जाने वाले protected static सहायक तरीके हैं।एफ # 3.0

public abstract class Processor { 
    public abstract void Process(); 
    protected static void Helper(object arg) { } 
} 

एफ # में, उन सहायक तरीकों में से एक एक प्रथम श्रेणी समारोह के रूप में पारित हो जाता है:

type DerivedProcessor() = 
    inherit Processor() 

    let init f = 
    f() 

    override x.Process() = 
    init Processor.Helper 

यह 2.0 में बिना किसी शिकायत के संकलित है, लेकिन 3.0 में एक त्रुटि पैदा करता है:

A protected member is called or 'base' is being used. This is only allowed in the direct implementation of members since they could escape their object scope.

ठीक है, यह अनुपालन करने में काफी आसान है, बस किसी अन्य स्थिर सदस्य

static member private HelperWrapper(arg) = Processor.Helper(arg) 
में कॉल को लपेटें

और उस इंटीड को पास करें। पर क्यों?

सी # इस पैटर्न के साथ कोई समस्या नहीं है।

public class HappyToCompile : Processor { 
    private void Init(Action<object> f) { 
     f(null); 
    } 

    public override void Process() { 
     Init(Helper); 
    } 
} 

सवाल:

  1. क्यों सख्त जाँच करता है जोड़ा गया था?
  2. (और संबंधित) इस तरह के एक छोटे से कामकाजी पते में क्या भयानक समस्या है?
  3. क्या कोई बेहतर डिज़ाइन है जिसे प्रोत्साहित किया जाना चाहिए?

उत्तर

5

मेरे मानसिक भाषा डिजाइन कौशल का उपयोग करके, मुझे लगता है कि एफ # 2.0 अविश्वसनीय कोड उत्पन्न कर रहा है। सी # में संबंधित मुद्दे की व्याख्या के लिए एरिक लिपर्ट के ब्लॉग पर this पोस्ट देखें (जिसे सी # 4, आईआईआरसी के बाद से तय किया गया है)।

संक्षेप में, जब आप एक एफ # फ़ंक्शन बनाते हैं तो आप वास्तव में FSharpFunc<_,_> से प्राप्त एक नई कक्षा बना रहे हैं, और उस वर्ग के भीतर से आपकी संरक्षित विधि को कॉल करना वैध नहीं है क्योंकि यह विरासत श्रृंखला में नहीं है।

बेशक, इन कॉलों को अस्वीकार करने के बजाए, कंपाइलर केवल वही कर सकता है जो आप कर रहे हैं (एक निजी विधि बनाएं और इसका उपयोग करें), लेकिन शायद लाभों को उस सुधार को लागू करने की लागत से अधिक नहीं होना चाहिए।

+0

आपने पहले प्रश्न का उत्तर दिया, और एरिक का ब्लॉग दूसरा जवाब देता है। 'Func <_> 'और' FSharpFunc <_> 'के बीच अंतरों पर चमकना आसान है। 'संरक्षित 'को खत्म करने के लिए इसे कैसे दोहराया जा सकता है? – Daniel

+1

अच्छा, यह पहली जगह क्यों संरक्षित है? यदि आप इसे केवल उप-वर्गों तक पहुंच योग्य बनाना चाहते हैं तो वास्तव में ऐसा नहीं है जो आप कर सकते हैं। शायद आप 'हेल्पर' को विधि के बजाय 'एक्शन ' प्रकार की संरक्षित संपत्ति के रूप में बेनकाब कर सकते हैं, यदि आप उम्मीद करते हैं कि इसे किसी प्रतिनिधि के रूप में पास किया जाए। – kvb

+3

यह [_Breaking Changes_] (http://msdn.microsoft.com/en-us/library/hh416791) के लिए एक अच्छा जोड़ा होगा। एक और [हालिया प्रश्न] (http://stackoverflow.com/q/11978234/162396) भी एक अच्छा उम्मीदवार हो सकता है। – Daniel