2008-09-02 6 views
17

Я унаследовал большое приложение VB6 на моем текущем рабочем месте. Я немного изучаю VB6 на работе, и у меня есть ряд проблем. Основная проблема на данный момент - я не могу понять, как проверить, существует ли ключ в объекте Collection. Может ли кто-нибудь помочь?Проверьте, существует ли запись в коллекции VB6?

ответ

8

Я всегда делал это с помощью функции, как это:

public function keyExists(myCollection as collection, sKey as string) as Boolean 
    on error goto handleerror: 

    dim val as variant 

    val = myCollection(sKey) 
    keyExists = true 
    exit sub 
handleerror: 
    keyExists = false 
end function 
22

@Mark Biek Ваш keyExists точно соответствует моей стандартной функции Exists(). Чтобы сделать класс более полезным для коллекций с открытым доступом и проверять числовые индексы, я бы рекомендовал изменить sKey и myCollection, чтобы их не вводить. Если функция будет использоваться с набором объектов, требуется «установить» (в строке, где установлен параметр val).

EDIT: Меня беспокоило, что я никогда не замечал различных требований к объектной функции Exists(), основанной на объектах. Я очень редко использую коллекции для не-объектов, но это казалось таким прекрасным узким местом для ошибки, которую было бы так сложно отследить, когда мне нужно было проверить существование. Поскольку обработка ошибок завершится неудачно, если обработчик ошибок уже активен, для получения новой области ошибок требуются две функции. Только функция Exists() нужно всегда можно назвать:

Public Function Exists(col, index) As Boolean 
On Error GoTo ExistsTryNonObject 
    Dim o As Object 

    Set o = col(index) 
    Exists = True 
    Exit Function 

ExistsTryNonObject: 
    Exists = ExistsNonObject(col, index) 
End Function 

Private Function ExistsNonObject(col, index) As Boolean 
On Error GoTo ExistsNonObjectErrorHandler 
    Dim v As Variant 

    v = col(index) 
    ExistsNonObject = True 
    Exit Function 

ExistsNonObjectErrorHandler: 
    ExistsNonObject = False 
End Function 

И проверить функциональность:

Public Sub TestExists() 
    Dim c As New Collection 

    Dim b As New Class1 

    c.Add "a string", "a" 
    c.Add b, "b" 

    Debug.Print "a", Exists(c, "a") ' True ' 
    Debug.Print "b", Exists(c, "b") ' True ' 
    Debug.Print "c", Exists(c, "c") ' False ' 
    Debug.Print 1, Exists(c, 1) ' True ' 
    Debug.Print 2, Exists(c, 2) ' True ' 
    Debug.Print 3, Exists(c, 3) ' False ' 
End Sub 
+1

Чтобы избежать этой проблемы, то лучше опустить часть присваивания, то есть падение инструкции Set O = Col (индекс) или v = Col (индекс) и объявление переменного, а просто писать седловины. индекс объекта, который работает одинаково с объектами и простыми значениями. – Clon 2016-06-24 07:29:25

+1

Теперь я вижу, что это было уже продемонстрировано Христианом Хейтером. – Clon 2016-06-24 08:13:33

5

Как указывает Томас, вам необходимо установить объект вместо Пусть. Вот общая функция из библиотеки, которая работает для значений и объектов типов:

Public Function Exists(ByVal key As Variant, ByRef col As Collection) As Boolean 

'Returns True if item with key exists in collection 

On Error Resume Next 

Const ERR_OBJECT_TYPE As Long = 438 
Dim item As Variant 

'Try reach item by key 
item = col.item(key) 

'If no error occurred, key exists 
If Err.Number = 0 Then 
    Exists = True 

'In cases where error 438 is thrown, it is likely that 
'the item does exist, but is an object that cannot be Let 
ElseIf Err.Number = ERR_OBJECT_TYPE Then 

    'Try reach object by key 
    Set item = col.item(key) 

    'If an object was found, the key exists 
    If Not item Is Nothing Then 
     Exists = True 
    End If 

End If 

Err.Clear 

End Function 

Как также посоветовал Томас, вы можете изменить тип коллекции для объекта обобщать это. Синтаксис .Item (key) используется большинством классов коллекций, поэтому это может быть полезно.

EDIT Похоже, я сам был избит до удара самим Томасом. Однако для более простого повторного использования я лично предпочитаю одну функцию без личных зависимостей.

3

Использование обработчика ошибок для обнаружения случаев, когда ключ не существует в коллекции, может сделать отладку с опцией «break on all errors» довольно раздражающей. Чтобы избежать нежелательных ошибок, я довольно часто создаю класс, который хранит объекты в коллекции и все ключи в словаре. Словарь существует (ключ) -функция, поэтому я могу вызвать это, прежде чем пытаться получить объект из коллекции. Вы можете хранить строки только в словаре, поэтому коллекция необходима, если вам нужно хранить объекты.

+0

Неправильно: вы можете хранить любые объекты/значения в Dictiionary https://msdn.microsoft.com/en-us/library/x4k5wbx4%28v= vs.84% 29.aspx «Элементы могут быть любыми формами данных» – Clon 2016-06-24 07:22:04

2

Лучшим решением было бы написать функцию TryGet. Много времени, когда вы собираетесь проверять, существует, а затем получает элемент. Сэкономьте время, сделав это одновременно.

public Function TryGet(key as string, col as collection) as Variant 
    on error goto errhandler 
    Set TryGet= col(key) 
    exit function 
errhandler: 
    Set TryGet = nothing 
end function 
2

см http://www.visualbasic.happycodings.com/Other/code10.html реализация здесь имеет преимущество также при необходимости возвращения найденного элемента, и работает с объектными/нативных типов (в соответствии с комментариями).

не воспроизводится здесь, так как ссылка больше не доступны:

Определить, если элемент существует в коллекции

Следующий код показывает, как определить, если элемент существует в коллекции.

Option Explicit 

'Purpose  : Determines if an item already exists in a collection 
'Inputs  : oCollection   The collection to test for the existance of the item 
'    vIndex    The index of the item. 
'    [vItem]    See Outputs 
'Outputs  : Returns True if the item already exists in the collection. 
'    [vItem] The value of the item, if it exists, else returns "empty". 
'Notes  : 
'Example  : 

Function CollectionItemExists(vIndex As Variant, oCollection As Collection, Optional vItem As Variant) As Boolean 
    On Error GoTo ErrNotExist 

    'Clear output result 
    If IsObject(vItem) Then 
     Set vItem = Nothing 
    Else 
     vItem = Empty 
    End If 

    If VarType(vIndex) = vbString Then 
     'Test if item exists 
     If VarType(oCollection.Item(CStr(vIndex))) = vbObject Then 
      'Return an object 
      Set vItem = oCollection.Item(CStr(vIndex)) 
     Else 
      'Return an standard variable 
      vItem = oCollection.Item(CStr(vIndex)) 
     End If 
    Else 
     'Test if item exists 
     If VarType(oCollection.Item(Int(vIndex))) = vbObject Then 
      'Return an object 
      Set vItem = oCollection.Item(Int(vIndex)) 
     Else 
      'Return an standard variable 
      vItem = oCollection.Item(Int(vIndex)) 
     End If 
    End If 
    'Return success 
    CollectionItemExists = True 
    Exit Function 
ErrNotExist: 
    CollectionItemExists = False 
    On Error GoTo 0 
End Function 

'Demonstration routine 
Sub Test() 
    Dim oColl As New Collection, oValue As Variant 

    oColl.Add "red1", "KEYA" 
    oColl.Add "red2", "KEYB" 
    'Return the two items in the collection 
    Debug.Print CollectionItemExists("KEYA", oColl, oValue) 
    Debug.Print "Returned: " & oValue 
    Debug.Print "-----------" 
    Debug.Print CollectionItemExists(2, oColl, oValue) 
    Debug.Print "Returned: " & oValue 
    'Should fail 
    Debug.Print CollectionItemExists("KEYC", oColl, oValue) 
    Debug.Print "Returned: " & oValue 
    Set oColl = Nothing 
End Sub 
24

Мой стандартной функции очень просто. Это будет работать независимо от типа элемента, поскольку он не беспокоится о выполнении какого-либо присвоения, он просто выполняет свойство collection get.

Public Function Exists(ByVal oCol As Collection, ByVal vKey As Variant) As Boolean 

    On Error Resume Next 
    oCol.Item vKey 
    Exists = (Err.Number = 0) 
    Err.Clear 

End Function 
3

Утверждение «обработка ошибок завершится неудачно, если обработчик ошибок уже активен» частично отчасти прав.

В вашей программе может быть несколько обработчиков ошибок.
Таким образом, можно использовать одну и ту же функциональность только в одной функции.
Просто переписать код так:

Public Function Exists(col, index) As Boolean 
Dim v As Variant 

TryObject: 
    On Error GoTo ExistsTryObject 
     Set v = col(index) 
     Exists = True 
     Exit Function 

TryNonObject: 
    On Error GoTo ExistsTryNonObject 

     v = col(index) 
     Exists = True 
     Exit Function 

ExistsTryObject: 
    ' This will reset your Err Handler 
    Resume TryNonObject 

ExistsTryNonObject: 
     Exists = False 
End Function 

Однако, если бы вы только включить код в разделе TryNonObject подпрограммы, это дало бы ту же самую информацию.
Это будет выполнено как для объектов, так и для не-объектов. Это ускорит ваш код для не-объектов, однако, поскольку вам нужно будет выполнить только один оператор, чтобы утверждать, что элемент существует в коллекции.

0

При поиске такой функции я разработал ее следующим образом. Это должно работать с объектами и не-объектами без назначения новых переменных.

Public Function Exists(ByRef Col As Collection, ByVal Key) As Boolean 
    On Error GoTo KeyError 
    If Not Col(Key) Is Nothing Then 
     Exists = True 
    Else 
     Exists = False 
    End If 

    Exit Function 
KeyError: 
    Err.Clear 
    Exists = False 
End Function