2017-06-20 1 views
7

वहाँ एफ # में वर्ग-स्तर और सदस्य स्तर के आत्म पहचानकर्ता के बीच किसी भी अर्थ अंतर है? इस वर्ग बनामएफ # में कक्षा स्तर और सदस्य स्तर के आत्म-पहचानकर्ता के बीच अंतर?

type MyClass2(dataIn) as self = 
    let data = dataIn 
    do 
     self.PrintMessage() 
    member this.Data = data 
    member this.PrintMessage() = 
     printfn "Creating MyClass2 with Data %d" this.Data 

: उदाहरण के लिए, इस वर्ग पर विचार

type MyClass2(dataIn) as self = 
    let data = dataIn 
    do 
     self.PrintMessage() 
    member this.Data = data 
    member this.PrintMessage() = 
     printfn "Creating MyClass2 with Data %d" self.Data 

फर्क सिर्फ इतना संदर्भ PrintMessage के कार्यान्वयन this अन्य में एक बनाम self में है। अर्थशास्त्र में कोई अंतर है? यदि नहीं, तो क्या एक दूसरे को पसंद करने के लिए एक स्टाइलिस्ट कारण है?

उत्तर

5

दोनों के बीच कोई वास्तविक अर्थ अंतर नहीं है। अंगूठे के नियम के रूप में, मैं आपके पहले उदाहरण के साथ जाने का सुझाव देता हूं - पहचानकर्ता को पसंद करें जो गुंजाइश के करीब है, इससे बाद में कोड को पढ़ने और पुन: सक्रिय करना आसान हो जाता है। एक तरफ ध्यान दें के रूप में, लोगों को आम तौर पर this का उपयोग करेगा दोनों वर्ग और सदस्य स्तर के पहचानकर्ता के लिए जो मामले सदस्य स्तर के एक छाया वर्ग स्तर के एक में।

इन स्थितियों से इस प्रकार में, यह ILSpy की तरह एक disassembler में संकलित कोड को देखने के लिए उपयोगी है। यदि आप ऐसा करते हैं, तो आप पाएंगे कि केवल अंतर एक अतिरिक्त शून्य जांच है जो self.Data मामले में डाला गया है।

दूसरी तरफ, कक्षा के स्तर के पहचानकर्ता का उपयोग करने वाले वर्ग के बीच एक अंतर होता है और ऐसा नहीं होता है (प्रारंभिक जांच की श्रृंखला सभी वर्ग के सदस्यों में डाली जाती है)। यदि संभव हो तो उन्हें रखने से बचाना सबसे अच्छा है, और आपका उदाहरण एक की आवश्यकता के लिए फिर से लिखा जा सकता है।

4

scrwtp से उल्लेख किया है, this एक आमतौर पर इस्तेमाल किया पहचानकर्ता हो रहा है और यह मेरी प्राथमिकता है। एक और बहुत आम x है। मैं क्लास-स्तरीय पहचानकर्ता का उपयोग करता हूं जब इसे कक्षा में कई बार उपयोग किया जाता है और निश्चित रूप से जब इसे कन्स्ट्रक्टर में उपयोग किया जाता है। और उन मामलों में मैं सदस्य स्तर पहचानकर्ता के रूप में __ (दो अंडरस्कोर) का उपयोग करता हूं, यह इंगित करने के लिए कि मान को अनदेखा किया गया है। आप _ उपयोग कर सकते हैं नहीं है और वास्तव में इसे अनदेखा के रूप में यह एक संकलन त्रुटि है, लेकिन linting उपकरण अक्सर __ एक ही बात के रूप में मानते हैं और आपको एक अप्रयुक्त पहचानकर्ता के बारे में चेतावनी देने से बचा जाएगा।

आप एक वर्ग स्तर के पहचानकर्ता जोड़ सकते हैं और उसका उपयोग नहीं करते आपको यह चेतावनी मिलती है:

पुनरावर्ती वस्तु संदर्भ 'स्वयं' अप्रयुक्त है। एक रिकर्सिव ऑब्जेक्ट संदर्भ की उपस्थिति इस और व्युत्पन्न प्रकारों के सदस्यों को रनटाइम प्रारंभिक जांच जोड़ती है। इस रिकर्सिव ऑब्जेक्ट संदर्भ को हटाने पर विचार करें।

इस कोड पर विचार करें:

type MyClass() = 
    member self.X = self 

type MyClassAsSelf() as self = 
    member __.X = self 

type MyClassAsSelfUnused() as self = // <-- warning here 
    member __.X =() 

यह है कि क्या इन कक्षाओं के संकलन के बाद की तरह/decompiling देखो:

public class MyClass 
{ 
    public Program.MyClass X 
    { 
     get 
     { 
      return this; 
     } 
    } 

    public MyClass() : this() 
    { 
    } 
} 
public class MyClassAsSelf 
{ 
    internal FSharpRef<Program.MyClassAsSelf> self = new FSharpRef<Program.MyClassAsSelf>(null); 

    internal int [email protected]; 

    public Program.MyClassAsSelf X 
    { 
     get 
     { 
      if ([email protected] < 1) 
      { 
       LanguagePrimitives.IntrinsicFunctions.FailInit(); 
      } 
      return LanguagePrimitives.IntrinsicFunctions.CheckThis<Program.MyClassAsSelf>(this.self.contents); 
     } 
    } 

    public MyClassAsSelf() 
    { 
     FSharpRef<Program.MyClassAsSelf> self = this.self; 
     this..ctor(); 
     this.self.contents = this; 
     [email protected] = 1; 
    } 
} 
public class MyClassAsSelfUnused 
{ 
    internal int [email protected]; 

    public Unit X 
    { 
     get 
     { 
      if ([email protected] < 1) 
      { 
       LanguagePrimitives.IntrinsicFunctions.FailInit(); 
      } 
     } 
    } 

    public MyClassAsSelfUnused() 
    { 
     FSharpRef<Program.MyClassAsSelfUnused> self = new FSharpRef<Program.MyClassAsSelfUnused>(null); 
     FSharpRef<Program.MyClassAsSelfUnused> self2 = self2; 
     this..ctor(); 
     self.contents = this; 
     [email protected] = 1; 
    } 
} 

ध्यान दें कि एक जांच है कि एक चर परिवर्तक में सेट किया गया है। यदि चेक विफल रहता है तो फ़ंक्शन को कॉल किया जाता है: LanguagePrimitives.IntrinsicFunctions.FailInit()

System.InvalidOperationException:: यह अपवाद उत्पन्न है एक वस्तु या मूल्य का प्रारंभ एक वस्तु के परिणामस्वरूप या मूल्य रिकर्सिवली इससे पहले कि यह पूरी तरह से आरंभ किया गया था एक्सेस किए जा रहे।

मुझे लगता है कि चेतावनी बस इतना है कि आप एक अनावश्यक रनटाइम चेक के मामूली ओवरहेड से बच सकते हैं। हालांकि, मुझे नहीं पता कि स्थिति को कैसे बनाया जाए जहां त्रुटि फेंक दी गई है, इसलिए मुझे चेक का सही उद्देश्य पता नहीं है। शायद कोई और इस पर प्रकाश डाल सकता है?

+1

जब विरासत चित्र में आती है तो यह प्रासंगिक हो जाता है - मुझे याद है कि यह एक विशेष रूप से बालों वाले परिदृश्य में एक मूल सारणी वर्ग के साथ स्वयं पहचानकर्ता है। लेकिन मेरे पास यहां देने के लिए एक हाथ, आत्मनिर्भर उदाहरण नहीं है। – scrwtp

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