खोज…


परिचय

ByRef और ByVal संशोधक एक प्रक्रिया के हस्ताक्षर का हिस्सा हैं और इंगित करते हैं कि कैसे एक तर्क एक प्रक्रिया को पारित किया जाता है। VBA में एक पैरामीटर ByRef पारित किया जाता है जब तक कि अन्यथा निर्दिष्ट नहीं किया जाता है (अर्थात अनुपस्थित होने पर ByRef निहित है)।

नोट : कई अन्य प्रोग्रामिंग भाषाओं में (VB.NET सहित), यदि कोई संशोधक निर्दिष्ट नहीं किया गया है, तो पैरामीटर को मूल रूप से मान से पास किया जाता है: संभावित भ्रम से बचने के लिए ByRef संशोधक को स्पष्ट रूप से निर्दिष्ट करने पर विचार करें।

टिप्पणियों

पासिंग ऐरे

एरे को संदर्भ द्वारा पारित किया जाना चाहिए। यह कोड संकलित करता है, लेकिन रन-टाइम त्रुटि 424 "ऑब्जेक्ट आवश्यक" उठाता है:

Public Sub Test()
    DoSomething Array(1, 2, 3)
End Sub

Private Sub DoSomething(ByVal foo As Variant)
    foo.Add 42
End Sub

यह कोड संकलित नहीं करता है:

Private Sub DoSomething(ByVal foo() As Variant) 'ByVal is illegal for arrays
    foo.Add 42
End Sub

पासिंग सिंपल वेरिएबल्स बायफ एंड बाइवाल

ByRef या ByVal इंगित करता है कि क्या CalledProcedure द्वारा CalledProcedure को एक तर्क का वास्तविक मान दिया गया है, या CallingProcedure एक संदर्भ (जिसे कुछ अन्य भाषाओं में पॉइंटर कहा जाता है) पास किया गया है CalledProcedure

यदि किसी तर्क को ByRef पास किया जाता है, तो तर्क का मेमोरी पता CalledProcedure को पास कर दिया जाता है और CalledProcedure द्वारा उस पैरामीटर के किसी भी संशोधन को CalledProcedure में मान कर दिया CallingProcedure

एक तर्क पारित हो जाता है तो ByVal , वास्तविक मूल्य, नहीं चर के लिए एक संदर्भ, को पारित कर दिया है CalledProcedure

एक सरल उदाहरण यह स्पष्ट रूप से दर्शाएगा:

Sub CalledProcedure(ByRef X As Long, ByVal Y As Long)
    X = 321
    Y = 654
End Sub

Sub CallingProcedure()
    Dim A As Long
    Dim B As Long
    A = 123
    B = 456

    Debug.Print "BEFORE CALL => A: " & CStr(A), "B: " & CStr(B)
    ''Result : BEFORE CALL => A: 123 B: 456

    CalledProcedure X:=A, Y:=B

    Debug.Print "AFTER CALL =  A: " & CStr(A), "B: " & CStr(B)
    ''Result : AFTER CALL => A: 321 B: 456
End Sub

एक और उदाहरण:

Sub Main()
    Dim IntVarByVal As Integer
    Dim IntVarByRef As Integer
    
    IntVarByVal = 5
    IntVarByRef = 10
    
    SubChangeArguments IntVarByVal, IntVarByRef '5 goes in as a "copy". 10 goes in as a reference
    Debug.Print "IntVarByVal: " & IntVarByVal 'prints 5 (no change made by SubChangeArguments)
    Debug.Print "IntVarByRef: " & IntVarByRef 'prints 99 (the variable was changed in SubChangeArguments)
End Sub

Sub SubChangeArguments(ByVal ParameterByVal As Integer, ByRef ParameterByRef As Integer)
    ParameterByVal = ParameterByVal + 2 ' 5 + 2 = 7 (changed only inside this Sub)
    ParameterByRef = ParameterByRef + 89 ' 10 + 89 = 99 (changes the IntVarByRef itself - in the Main Sub)
End Sub

ByRef


डिफ़ॉल्ट संशोधक

यदि कोई पैरामीटर किसी पैरामीटर के लिए निर्दिष्ट नहीं किया जाता है, तो उस पैरामीटर को संदर्भ द्वारा पारित किया जाता है।

Public Sub DoSomething1(foo As Long)
End Sub
Public Sub DoSomething2(ByRef foo As Long)
End Sub

foo पैरामीटर DoSomething1 और DoSomething2 दोनों में ByRef को पास करता है।

ध्यान रहे! यदि आप अन्य भाषाओं के अनुभव के साथ VBA में आ रहे हैं, तो यह आपके द्वारा उपयोग किए जा रहे व्यवहार के ठीक विपरीत व्यवहार की संभावना है। कई अन्य प्रोग्रामिंग भाषाओं में (VB.NET सहित), अंतर्निहित / डिफ़ॉल्ट संशोधक मान से पैरामीटर गुजरता है।


संदर्भ से गुजर रहा है

  • जब कोई मान ByRef , तो प्रक्रिया मान का संदर्भ प्राप्त करती है

    Public Sub Test()
        Dim foo As Long
        foo = 42
        DoSomething foo
        Debug.Print foo
    End Sub
    
    Private Sub DoSomething(ByRef foo As Long)
        foo = foo * 2
    End Sub
    

    उपरोक्त Test प्रक्रिया को कॉल करना 84 को आउटपुट करता है। DoSomething को foo दिया जाता है और मूल्य के लिए एक संदर्भ प्राप्त होता है, और इसलिए कॉलर के समान मेमोरी एड्रेस के साथ काम करता है।

  • जब एक संदर्भ ByRef पारित किया जाता है, तो प्रक्रिया सूचक को एक संदर्भ प्राप्त करती है

    Public Sub Test()
        Dim foo As Collection
        Set foo = New Collection
        DoSomething foo
        Debug.Print foo.Count
    End Sub
    
    Private Sub DoSomething(ByRef foo As Collection)
        foo.Add 42
        Set foo = Nothing
    End Sub
    

    उपरोक्त कोड रन-टाइम एरर 91 उठाता है, क्योंकि कॉलर किसी ऑब्जेक्ट के Count मेंबर को कॉल कर रहा है, जो अब मौजूद नहीं है, क्योंकि DoSomething को ऑब्जेक्ट पॉइंटर का संदर्भ दिया गया था और इसे लौटने से पहले Nothing सौंपा गया था।


मजबूरन ByVal को कॉल साइट पर

कॉल साइट पर कोष्ठकों का उपयोग करके, आप ByRef को ओवरराइड कर सकते हैं और एक तर्क को पास करने के लिए बाध्य कर सकते हैं ByVal :

Public Sub Test()
    Dim foo As Long
    foo = 42
    DoSomething (foo)
    Debug.Print foo
End Sub

Private Sub DoSomething(ByRef foo As Long)
    foo = foo * 2
End Sub

उपरोक्त कोड 42 को आउटपुट करता है, भले ही ByRef को स्पष्ट रूप से या स्पष्ट रूप से निर्दिष्ट किया गया हो।

ध्यान रहे! इस वजह से, प्रक्रिया कॉल में बाहर के कोष्ठकों का उपयोग करके आसानी से बग का परिचय दिया जा सकता है। प्रक्रिया के नाम और तर्क सूची के बीच व्हाट्सएप पर ध्यान दें:

bar = DoSomething(foo) 'function call, no whitespace; parens are part of args list
DoSomething (foo) 'procedure call, notice whitespace; parens are NOT part of args list
DoSomething foo 'procedure call does not force the foo parameter to be ByVal

ByVal

मान से गुजरना

  • जब कोई मान ByVal , तो प्रक्रिया मूल्य की एक प्रति प्राप्त करती है

    Public Sub Test()
        Dim foo As Long
        foo = 42
        DoSomething foo
        Debug.Print foo
    End Sub
    
    Private Sub DoSomething(ByVal foo As Long)
        foo = foo * 2
    End Sub
    

    उपरोक्त Test प्रक्रिया को कॉल करना 42 आउटपुट करता है। DoSomething को foo दिया जाता है और मूल्य की एक प्रति प्राप्त होती है । प्रतिलिपि को 2 से गुणा किया जाता है, और फिर जब प्रक्रिया से बाहर निकलता है तो उसे छोड़ दिया जाता है; कॉलर की कॉपी कभी नहीं बदली गई थी।

  • जब एक संदर्भ ByVal , तो प्रक्रिया सूचक की एक प्रति प्राप्त करती है

    Public Sub Test()
        Dim foo As Collection
        Set foo = New Collection
        DoSomething foo
        Debug.Print foo.Count
    End Sub
    
    Private Sub DoSomething(ByVal foo As Collection)
        foo.Add 42
        Set foo = Nothing
    End Sub
    

    उपरोक्त Test प्रक्रिया को DoSomething आउटपुट 1. DoSomething को foo दिया जाता है और Collection वस्तु के लिए सूचक की एक प्रति प्राप्त करता है । क्योंकि Test स्कोप में foo ऑब्जेक्ट वैरिएबल एक ही ऑब्जेक्ट को इंगित करता है, DoSomething में एक आइटम जोड़ने से आइटम को उसी ऑब्जेक्ट में जोड़ा जाता है। क्योंकि यह पॉइंटर की एक प्रति है, इसके Nothing भी नहीं के संदर्भ को सेट करने से कॉल करने वाले की स्वयं की प्रति प्रभावित Nothing होती है।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow