2010-11-14 9 views
8

मुझे पता है कि अगर के बराबर मौजूद चाहते हैं (.net)VB6 बराबर सूची <someclass>

list<somefixedclass> 

VB6 में

मुझे पता है कि VB6 में संग्रह मौजूद हैं, लेकिन यह वस्तु (संस्करण) का उपयोग करता है के बजाय एक विशिष्ट वस्तु।

धन्यवाद।

उत्तर

21

VB.NET में पाए गए जेनेरिक List<T> पर वीबी 6 में कोई प्रत्यक्ष समतुल्य नहीं है। हालांकि, वीबी 6 में Collection जैसी चीज है, जो समान कार्यक्षमता प्रदान करती है। प्राथमिक अंतर यह है कि एक वीबी 6 Collectionदृढ़ता से टाइप नहीं किया गया, जिसका अर्थ है कि सभी ऑब्जेक्ट संग्रह में Variants के रूप में संग्रहीत हैं। कुछ मामलों में, यह फायदेमंद हो सकता है, क्योंकि यह आपको एक ही संग्रह में कई अलग-अलग प्रकार के डेटा स्टोर करने की अनुमति देता है, और वास्तव में, वीबी आंतरिक रूप से इस ऑब्जेक्ट का उपयोग करता है। Collection और अप-कास्ट ऑब्जेक्ट्स का उपयोग करने के लिए पर्याप्त आसान है क्योंकि उन्हें कक्षा से पुनर्प्राप्त किया जाता है, लेकिन आप ऐसा कर सकते हैं। वीबी रनटाइम में दृढ़ता से टाइप किए गए संग्रह को लागू करना संभव नहीं है।

कहा जा रहा है कि, एक ऐसा कामकाज है जिसे आप कार्यान्वित कर सकते हैं। इसी तरह जेनिक्स पेश किए जाने से पहले वीबीएनईटी के प्रारंभिक संस्करणों में संग्रह कैसे लागू किए गए थे, आप कक्षा में Collection को लपेट सकते हैं, जहां आंतरिक Collection तक पहुंच केवल उन वर्गों के माध्यम से होती है जिन्हें आप इस कक्षा से एक्सपोज़ करते हैं। इस डिजाइन पैटर्न को आमतौर पर "कस्टम संग्रह" के रूप में जाना जाता है।

इसका स्वचालित रूप से कास्टिंग को संभालने का लाभ होता है, और आपके कोड के उपभोक्ताओं को इस तरह के कार्यान्वयन विवरणों को याद रखने के लिए याद रखने से लाभ होता है। यह (सभी संभावनाओं) की संभावना का ख्याल रखता है कि आप रन-टाइम पर संग्रह के माध्यम से लूपिंग करेंगे, जिसमें केवल एक प्रकार का ऑब्जेक्ट होना चाहिए, लेकिन गलती से एक दूसरा, असंगत प्रकार का ऑब्जेक्ट जोड़ा गया जो आपके कोड का कारण बनता है अपवाद फेंकने के लिए। निस्संदेह, नुकसान यह है कि आपको अपने कस्टम संग्रह पर सार्वजनिक विधियों के रूप में Collection ऑब्जेक्ट द्वारा पहले से प्रदान की गई अधिकांश कार्यक्षमताओं को फिर से कार्यान्वित करना होगा।

तरीका यहां बताया गया है कि के बारे में जाना हो सकता है की एक उदाहरण है:

Public Class CustomerCollection 

    ''#Internal collection, exposed by this class 
    Private m_Customers As Collection 

    Private Sub Class_Initialize() 
     ''#Set up the internal collection 
     Set m_Customers = New Collection 
    End Sub 

    Public Sub Add(ByVal cust as Customer, Optional ByVal key as String) 
     ''#Add the Customer object to the internal collection 
     If IsMissing(key) Then 
      m_Customers.Add cust 
     Else 
      m_Customers.Add cust, key 
     End If 
    End Sub 

    Public Property Get Count() As Integer 
     ''#Return the number of objects in the internal collection 
     Count = m_Customers.Count 
    End Property 

    Public Sub Remove(ByVal index As Variant) 
     ''#Remove the specified object from the internal collection, 
     ''# either by its index or its key 
     m_Customers.Remove index 
    End Sub 

    Public Function Item(ByVal index As Variant) as Customer 
     ''#Return the specified object from the internal collection, 
     ''# either by its index or its key 
     Set Item = m_Customers.Item(index) 
    End Function 

    Public Sub Clear() 
     ''#Removes all objects from the internal collection 
     Set m_Customers = New Collection 
    End Sub 

End Class 

ध्यान दें कि संग्रह के डिफ़ॉल्ट पद्धति के रूप में कस्टम संग्रह के Item गुण सेट करने के लिए (जैसे निर्मित Collection वस्तु), तो आपको जरूरत है क्रम में वीबी 6 IDE में निम्न चरणों का पालन करने के लिए:

  1. "उपकरण" मेनू से, क्लिक करें "प्रक्रिया विशेषता"

  2. "नाम" कॉम्बो बॉक्स से अपनी कस्टम कक्षा का नाम चुनें।

  3. जब संवाद प्रकट होता है, तो "उन्नत" बटन पर क्लिक करें।

  4. "प्रक्रिया आईडी" कॉम्बो बॉक्स में "(डिफ़ॉल्ट)" आइटम का चयन करें।

  5. क्लिक करें "ठीक है"


आप भी For Each वाक्य रचना (भी तरह निर्मित Collection वस्तु), आप एक जोड़ सकते हैं का उपयोग कर अपने कस्टम वर्ग की गणना अनुमति देने के लिए करना चाहते हैं तो अपने कस्टम वर्ग के लिए NewEnum समारोह:

Public Property Get NewEnum() As IUnknown 
    ''#Provides support for enumeration using For Each 
    Set NewEnum = m_Customers.[_NewEnum] 
End Property 

कर लेने के बाद, आप इस संपत्ति का उपयोग करने के वीबी को निर्देश देने की जरूरत है:

  1. पहले की तरह, "उपकरण" मेनू

  2. से "प्रक्रिया विशेषता" संवाद खोलने "नाम" कॉम्बो बॉक्स से अपने कस्टम वर्ग के नाम का चयन करें।

  3. जब संवाद प्रकट होता है, तो "उन्नत" बटन पर क्लिक करें।

  4. "प्रक्रिया आईडी" कॉम्बो बॉक्स में "-4" संख्या टाइप करें।

  5. क्लिक करें "ठीक है"

+0

+1। IMHO यह (सही) समाधान कई मामलों में सहायक होता है, लेकिन कुछ अन्य मामलों के लिए यह थोड़ा अधिक oversized हो सकता है। –

+0

@ डॉक्टर ब्राउन: सहमत। शब्दों की उत्कृष्ट पसंद। –

+2

+1 लेकिन बॉयलरप्लेट स्वयं को न बनाएं। फ्रांसेस्को बालेना ने लिखा [संग्रह क्लासमास्टर] (http://www.angryhacker.com/download/colclassmaster.zip), वीबी 6 आईडीई के लिए एक मुफ्त प्लग-इन जो आपके लिए स्वचालित रूप से करेगा। यह अब कृपया [AngryHacker] द्वारा होस्ट किया गया है (http://angryhacker.com/blog/archive/2008/05/01/vb6-swiss-army-knife.aspx)) – MarkJ

0

वीबी 6 एक प्राचीन भाषा है। इसमें टेम्पलेट जैसी प्रकार नहीं हैं क्योंकि आधुनिक भाषाओं में हैं (सी ++, सी #, जावा)। तो आपको संग्रह में वेरिएंट के रूप में अपनी ऑब्जेक्ट्स को स्टोर करना होगा और फिर उन्हें बाद में अपने ऑब्जेक्ट प्रकार पर डालना होगा।

+0

मैं आमतौर पर विभिन्न परियोजनाओं में सी # के साथ काम करता हूं लेकिन स्टैंड अकेले निष्पादन योग्य के लिए काम करता हूं। क्यूं कर?। चूंकि .NET धीमा है (ज्यादातर मामलों में), इसे आसानी से हटाया जा सकता है, इसे नेट फ्रेमवर्क की आवश्यकता होती है, यह अधिकांश ओएस के साथ काम नहीं करती है, vb6 विंडोज 95 से लिनक्स तक चल सकता है (बिना किसी प्रयास के शराब के साथ)। और स्टैंड के लिए जावा अकेले निष्पादन योग्य सबसे अच्छा "फंकी" है। मेरा दूसरा विकल्प डेल्फी और सी ++ है लेकिन यह एक और कहानी है। – magallanes

+4

आपकी तर्क गलत है। वीबी 6 में सामान्य प्रकार की कमी नहीं है क्योंकि यह एक प्राचीन भाषा है (जो यह नहीं है, सी ++ बहुत पुराना है), लेकिन क्योंकि इस तरह की जटिलताओं को उस भाषा से दूर रखने का एक सचेत निर्णय था जिसमें पूरी तरह से अलग जगह है। – GSerg

+0

ध्यान दें कि मैंने डाउनवोट नहीं किया है, क्योंकि -2 एक पोस्ट के लिए पर्याप्त कम है जो वास्तव में सही उत्तर प्रदान करता है।लेकिन मुझे लगता है कि यह इंगित करने लायक है कि हम प्रोग्रामर के रूप में हमेशा * जो भी भाषा चाहते हैं उसे चुनने की लक्जरी नहीं होती है। आपका सुझाव वास्तव में सहायक नहीं है, और शायद किसी भी चीज़ से ज्यादा निराशाजनक है। और इसके लायक होने के लिए, आपको "प्राचीन" सी # 1.1 में जेनेरिक से पहले जीवन याद हो सकता है ... –

2

संपादित करें: यदि कोड़ी ग्रे की समाधान आपकी आवश्यकताओं के लिए भी बड़े है, आप के बजाय इस प्रकार की कोशिश कर सकते "गरीब आदमी का सूची" समाधान,:

Dim l() as somefixedclass 
Redim l(0) 

'... 
'increase size dynamically: 
Redim Preserve l(ubound(l)+1) 
'... 
बेशक

, एक List<somefixedclass> (सी में #) या एक VB.NET में List(Of somefixedclass) अधिक "उपयोगकर्ता के अनुकूल" है क्योंकि इसमें खोज, निकालें, AddRange और कुछ अन्य उपयोगी चीजें हैं। पुरानी वीबी 6 निर्माण "खाली सूची" मामले के साथ बहुत बुरी तरह से काम करता है। भूलना नहीं है, < सूचीबद्ध करें ..> बड़ी सूचियों (आकार> 1000) के लिए वृद्धि का बेहतर प्रदर्शन है।

+0

हां, यह एक और विकल्प है, धन्यवाद – magallanes

+0

यह एक व्यावहारिक समाधान है, सिवाय इसके कि 'रेडीम संरक्षित' का प्रदर्शन हत्यारा हो सकता है यदि आप इसे स्वयं बहुत बुलाते हैं। वीबी 6 में सरणी या 'संग्रह' का उपयोग करना एक महत्वपूर्ण डिजाइन निर्णय है, और सबसे अच्छी सलाह यह है कि यदि आप समय से पहले की गई वस्तु की संख्या को जानते हैं (या बारीकी से अनुमान लगा सकते हैं), तो आपको एक सरणी चुननी चाहिए। प्रदर्शन 'संग्रह' से थोड़ा बेहतर है, लेकिन यदि आप गतिशील रूप से वस्तुओं को जोड़ और निकाल देंगे, तो 'संग्रह' शायद सबसे अच्छा विकल्प है। –

+0

@ कोडी ग्रे: हां वास्तव में, प्रदर्शन इस तरह खराब हो सकता है। सबसे वास्तविक दुनिया के कार्यक्रमों में मैंने पिछले 5 वर्षों में एक्सेल-वीबीए में लिखा था, सूची का 98% मामला 500 से कम प्रविष्टियों वाली एक सूची है, जहां यह समाधान पूरी तरह से पर्याप्त है। –

4

यहाँ ArrayList के हमारे कार्यान्वयन है। आप दृढ़ता से टाइप की गई कक्षा के लिए आधार के रूप में इसका उपयोग कर सकते हैं (स्पष्ट रूप से विरासत के माध्यम से नहीं बल्कि कोडीग्रे के उत्तर में व्यक्त की गई रचना के माध्यम से), लेकिन अगर आपको सुरक्षा की आवश्यकता नहीं है तो यह संग्रह वर्ग से काफी बेहतर है।

Option Explicit 

Private mavInternalArray() As Variant 
Private mlArraySize As Long 
Private mlCount As Long 
Private mlGrowSize As Long 
Private mfZeroIndex As Boolean 

'--------------------------------------------------------------------------------------- 
' Procedure Clear 
'--------------------------------------------------------------------------------------- 
Public Sub Clear() 
      Dim index As Long 

     For index = 0 To mlCount - 1 
      If IsObject(mavInternalArray(index)) Then 
       Set mavInternalArray(index) = Nothing 
      End If 
     Next index 
     mlCount = 0 

End Sub 



'--------------------------------------------------------------------------------------- 
' Procedure Swap 
'--------------------------------------------------------------------------------------- 
Public Sub Swap(Index1 As Long, index2 As Long) 
      Dim vTmp As Variant 


     If IsObject(mavInternalArray(index2)) Then 
      Set vTmp = mavInternalArray(index2) 
     Else 
      vTmp = mavInternalArray(index2) 
     End If 

     If IsObject(mavInternalArray(Index1)) Then 
      Set mavInternalArray(index2) = mavInternalArray(Index1) 
     Else 
      mavInternalArray(index2) = mavInternalArray(Index1) 
     End If 

     If IsObject(vTmp) Then 
      Set mavInternalArray(Index1) = vTmp 
     Else 
      mavInternalArray(Index1) = vTmp 
     End If 


End Sub 

Public Property Get ZeroIndex() As Boolean 
     ZeroIndex = mfZeroIndex 
End Property 

Public Property Let ZeroIndex(fZeroIndex As Boolean) 
     mfZeroIndex = fZeroIndex 
End Property 

Public Property Get GrowSize() As Long 
     GrowSize = mlGrowSize 
End Property 

Public Property Let GrowSize(lNewSize As Long) 
     Debug.Assert lNewSize > 0 
     mlGrowSize = lNewSize 
End Property 

Private Sub Class_Initialize() 
     mlGrowSize = 50 
     mlArraySize = mlGrowSize 
     mfZeroIndex = True 
     mlCount = 0 


     ReDim mavInternalArray(0 To mlGrowSize - 1) 

End Sub 

'--------------------------------------------------------------------------------------- 
' Procedure Remove 
'--------------------------------------------------------------------------------------- 
Public Sub Remove(index As Long) 
     Dim index2 As Long 


     For index2 = index To mlCount - 2 
      If IsObject(mavInternalArray(index2 + 1)) Then 
       Set mavInternalArray(index2) = mavInternalArray(index2 + 1) 
      Else 
       mavInternalArray(index2) = mavInternalArray(index2 + 1) 
      End If 
     Next index2 
      If mlCount <= 0 Then 
      Exit Sub 
      End If 
     mlCount = mlCount - 1 
     If IsObject(mavInternalArray(mlCount)) Then 
      Set mavInternalArray(mlCount) = Nothing 
     Else 
      mavInternalArray(mlCount) = False 
     End If 
End Sub 

'--------------------------------------------------------------------------------------- 
' Procedure Items 
'--------------------------------------------------------------------------------------- 
Public Function Items(index As Long) As Variant 
     If Not mfZeroIndex Then 
      index = index - 1 
     End If 

     If index < mlCount And index >= 0 Then 
      If IsObject(mavInternalArray(index)) Then 
       Set Items = mavInternalArray(index) 
      Else 
       Items = mavInternalArray(index) 
      End If 
     End If 
End Function 

Public Sub SetItem(index As Long, Item As Variant) 
     If Not mfZeroIndex Then 
      index = index - 1 
     End If 
     If IsObject(Item) Then 
      Set mavInternalArray(index) = Item 
     Else 
      mavInternalArray(index) = Item 
     End If 
End Sub 

'--------------------------------------------------------------------------------------- 
' Procedure Add 
'--------------------------------------------------------------------------------------- 
Public Function Add(vItem As Variant) As Long 

     mlCount = mlCount + 1 
     If mlCount > mlArraySize Then 
      mlArraySize = mlArraySize + mlGrowSize 
      ReDim Preserve mavInternalArray(0 To mlArraySize - 1) 
     End If 

     If IsObject(vItem) Then 
      Set mavInternalArray(mlCount - 1) = vItem 
     Else 
      mavInternalArray(mlCount - 1) = vItem 
     End If 

     Add = mlCount - 1 

End Function 

'--------------------------------------------------------------------------------------- 
' Procedure ItemArray 
'--------------------------------------------------------------------------------------- 
Public Function ItemArray() As Variant 
     Dim vReturnArray As Variant 

     vReturnArray = mavInternalArray 
     ReDim Preserve vReturnArray(0 To mlCount - 1) 
     ItemArray = vReturnArray 
End Function 

Public Function Count() As Long 
     Count = mlCount 
End Function 


'--------------------------------------------------------------------------------------- 
' Procedure Insert 
'--------------------------------------------------------------------------------------- 
Public Function Insert(index As Long, vItem As Variant) As Long 
     Dim index2 As Long 

     'Make sure array is large enough for a new item 
     mlCount = mlCount + 1 
     If mlCount > mlArraySize Then 
      mlArraySize = mlArraySize + mlGrowSize 
      ReDim Preserve mavInternalArray(0 To mlArraySize - 1) 
     End If 

     'Bump all the items with a higher index up one spot 

     If index >= mlCount - 1 Then 
      If IsObject(vItem) Then 
       Set mavInternalArray(mlCount - 1) = vItem 
      Else 
       mavInternalArray(mlCount - 1) = vItem 
      End If 
     Else 

      For index2 = mlCount - 1 To index + 1 Step -1 
       If IsObject(vItem) Then 
        Set mavInternalArray(index2) = mavInternalArray(index2 - 1) 
       Else 
        mavInternalArray(index2) = mavInternalArray(index2 - 1) 
       End If 
      Next index2 

      If IsObject(vItem) Then 
       Set mavInternalArray(index) = vItem 
      Else 
       mavInternalArray(index) = vItem 
      End If 
     End If 
     Insert = mlCount - 1 

End Function 


Public Sub Clone(ByRef cDestinationDynamicArray As clsDynamicArray) 
     Dim index As Long 

     If cDestinationDynamicArray Is Nothing Then 
      Set cDestinationDynamicArray = New clsDynamicArray 
     End If 

     cDestinationDynamicArray.Clear 

     For index = 0 To mlCount - 1 
      Call cDestinationDynamicArray.Add(mavInternalArray(index)) 
     Next index 

End Sub 

Public Property Get NewEnum() As IUnknown 
    ''#Provides support for enumeration using For Each 
    Set NewEnum = m_Customers.[_NewEnum] 
End Property 
+0

+1 दिलचस्प समाधान। जिज्ञासा से बाहर: क्या आपने इसे 'संग्रह' वर्ग की तुलना में अतिरिक्त/सम्मिलन के लिए तेजी से बेंचमार्क किया है? या आप किस तरह से मतलब था कि यह बेहतर था? –

+0

यह किस तरह से बेहतर है? संग्रह आपके जानकारियों के बिना गलती से एक शब्दकोश में बदल सकता है। फिर आपकी गिनती 5 कहें, लेकिन आइटम हैं (0,1,4,5,6) जब आप तत्व 3 तक पहुंचने का प्रयास करते हैं और त्रुटि प्राप्त करते हैं तो आपको एक त्रुटि मिलती है। साथ ही, यह तेज़ है यदि आप अपने सरणी के आकार के लिए उपयुक्त होने के लिए ग्रोसाइज सेट करते हैं (हाँ, यह हर बार बढ़ने पर दोगुना होकर खुद को बेहतर बना सकता है लेकिन यह माइक्रो-ऑप्टिमाइज़ेशन है जो अतिरिक्त कोड के लायक नहीं है)। हालांकि इन दिनों (जब यह लिखा गया था कि एक सीपीयू की गति लगभग 200 मेगाहट्र्ज थी) दक्षता महत्वपूर्ण नहीं है, बग नहीं है। –