VBA:声明新对象的两种方式的区别?(试图了解为什么我的解决方案有效) [英] VBA: Difference in two ways of declaring a new object? (Trying to understand why my solution works)

查看:21
本文介绍了VBA:声明新对象的两种方式的区别?(试图了解为什么我的解决方案有效)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在循环中创建了一个新对象,并将该对象添加到一个集合中;但是当我之后读回该集合时,它总是充满了我添加的最后一个对象.我想出了两种方法来解决这个问题,但我根本不明白为什么我最初的实现是错误的.

I was creating a new object within a loop, and adding that object to a collection; but when I read back the collection after, it was always filled entirely with the last object I had added. I've come up with two ways around this, but I simply do not understand why my initial implementation was wrong.

原文:

Dim oItem As Variant
Dim sOutput As String
Dim i As Integer

Dim oCollection As New Collection
For i = 0 To 10
    Dim oMatch As New clsMatch
    oMatch.setLineNumber i
    oCollection.Add oMatch
Next
For Each oItem In oCollection
    sOutput = sOutput & "[" & oItem.lineNumber & "]"
Next
MsgBox sOutput

这导致每个 lineNumber 都是 10;我显然不是在创建新对象,而是在循环中每次都使用相同的对象,尽管声明是在循环内部的.

This resulted in every lineNumber being 10; I was obviously not creating new objects, but instead using the same one each time through the loop, despite the declaration being inside of the loop.

所以,我在 Next 行之前添加了 Set oMatch = Nothing,这解决了问题,现在是 0 到 10.所以如果旧对象是明确销毁,那么它愿意创建一个新的吗?我会认为循环的下一次迭代会导致循环中声明的任何内容由于范围而被破坏?

So, I added Set oMatch = Nothing immediately before the Next line, and this fixed the problem, it was now 0 to 10. So if the old object was explicitly destroyed, then it was willing to create a new one? I would have thought the next iteration through the loop would cause anything declared within the loop do be destroyed due to scope?

好奇,我尝试了另一种声明新对象的方法:Dim oMatch As clsMatch:Set oMatch = New clsMatch.这也导致 0 到 10.

Curious, I tried another way of declaring a new object: Dim oMatch As clsMatch: Set oMatch = New clsMatch. This, too, results in 0 to 10.

谁能向我解释为什么第一个实现是错误的?

Can anyone explain to me why the first implementation was wrong?

推荐答案

Fink 的回答解决了您的主要问题,即您的第一个循环是向您的集合中添加对同一 'clsMatch' 实例的多个引用.我将详细说明为什么您的修复有效.

Fink's answer gets your main problem right, which is that your first loop is adding multiple references to the same instance of 'clsMatch' to your collection. I'll just elaborate on why your fix works.

在 VBA 中,像这样的一行:

In VBA, a line like:

Dim c As New Collection

实际上并没有创建一个新的集合.'Dim' 语句始终只是一个声明.将作为新"表单视为此内容的简写:

doesn't actually create a new collection. The 'Dim' statement is always just a declaration. Think of the 'As New' form as being shorthand for this:

Dim c As Collection
'...

'(later, when you're about to use 'c')

If c Is Nothing Then
    Set c = New Collection
End If

'...

这就是为什么通过将包含引用的变量设置为Nothing"来破坏引用的原因.[注意:对编辑此内容的人说不是"-这会改变答案的含义并使其不正确.请阅读原始问题.OP 发现将变量设置为 Nothing did 有效,我正在解释 为什么 是这种情况.] 当循环回到oMatch.setLineNumber"时行,VBA帮助"创建了一个新的 'clsMatch' 实例供您的 'oMatch' 变量引用,然后您的集合中有多个不同的实例.

That is why destroying your reference by setting the variable that contained it to 'Nothing' was working. [NOTE: to whomever edited this to say "was not" - that changes the meaning of the answer and makes it incorrect. Please read the original question. The OP found that setting the variable to Nothing did work, and I was explaing why that was the case.] When the loop came back around to the 'oMatch.setLineNumber' line, VBA "helpfully" created a new instance of 'clsMatch' for your 'oMatch' variable to refer to, and then you got multiple different instances in your collection.

明确地这样做可能会更好:

It would probably be better to do this explicitly:

Dim oMatch As clsMatch   

For i = 0 To 10                
    Set oMatch = New clsMatch                
    oMatch.setLineNumber i                
    oCollection.Add oMatch                
Next  

请注意(与 C/C++ 或 ??.NET 不同)Dim"声明的位置无关紧要.它不会在循环内多次执行",并且它声明的范围是过程范围的,即使它出现在循环内.

Note that (unlike in C/C++ or ??.NET) it doesn't matter where the 'Dim' declaration goes. It's not being "executed" multiple times inside the loop, and the scope of what it declares is procedure-wide even though it appears inside the loop.

这篇关于VBA:声明新对象的两种方式的区别?(试图了解为什么我的解决方案有效)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆