在VB6中,Property Set和Property Let有什么区别?

42

我刚刚创建了几个Property Set方法,但是它们没有编译。当我改为Property Let时,一切都很好。

后来我查看了文档,想要找到Property SetProperty Let之间的区别,但承认自己并不清楚。这两者有什么区别吗?如果有,能否请有经验的人士给予适当的解释和指导?


请仅返回翻译文本:相关:https://microsoft.public.vc.atl.narkive.com/Pmb6lPrM/the-difference-between-propput-and-propputref-in-idl, https://dev59.com/0HI-5IYBdhLWcg3weoFO - Solomon Ucko
3个回答

38

属性设置(Property Set)用于对象(例如类实例)

属性设值(Property Let)用于“普通”数据类型(例如字符串、布尔值、长整型等)


它与WithEvents无关,它是用于将对象引用作为属性返回。在许多情况下,您都希望这样做,最常见的情况是当您拥有任何类型的对象层次结构时。 - Bob77
错误。Property Get 用于将对象引用返回为属性,而不是 Property Set - mwolfe02
FunctionProperty Get 过程类似,Property Set 过程是一个单独的过程,可以接受参数,执行一系列语句并更改其参数的值。然而,不同于既返回一个值的 FunctionProperty Get 过程,你只能在对象引用赋值(Set 语句)的左侧使用 Property Set 过程。 - mwolfe02
+1 正确,Property Set 定义了一个可以在 Set 语句的左侧使用的属性。不过,我认为提到 WithEvents 有点令人困惑,它与解释差异并没有真正关联。Property Set 对于对象之间的一对一关系非常有用,这些对象可以在运行时动态地进行更改,即超出了 WithEvents 的范围。 - MarkJ
3
是的,对于“设置”一个属性 - 我完全理解错误了,我的错。最终就像上面指出的那样,它就像阅读手册一样简单。 - Bob77
@Bob:因为承认错误而加一分。如果我的语气显得严厉,我很抱歉,但我想澄清技术问题。既然我们正在道歉,我要承认我的原始措辞不必要地混淆了“Property Set”和“WithEvents”的问题。当我第一次学习VB6/VBA中的类时,我很难理解何时需要使用“Property Set”语句。我只是想提供一个常见的例子给OP。暗示它是唯一需要使用“Property Set”的情况是我的错误。希望新的措辞更清晰明了。 - mwolfe02

28

Property LetProperty Set 更加灵活。后者仅限于对象引用。如果你在类中有这个属性。

Private m_oPicture          As StdPicture

Property Get Picture() As StdPicture
    Set Picture = m_oPicture
End Property

Property Set Picture(oValue As StdPicture)
    Set m_oPicture = oValue
End Property

Property Let Picture(oValue As StdPicture)
    Set m_oPicture = oValue
End Property

您可以使用 Property Set Picture 方法进行调用。

Set oObj.Picture = Me.Picture
你可以使用 Property Let Picture 来同时调用两个。
Let oObj.Picture = Me.Picture
oObj.Picture = Me.Picture
实现属性集(Property Set)是其他开发者对于对象引用属性的期望,但有时甚至 Microsoft 只提供参考属性的 Property Let,导致出现了没有使用 Set 语句的非正常语法 "oObj.Object = MyObject"。在这种情况下,使用 Set 语句会导致编译时或运行时错误,因为 oObj 类上没有实现 Property Set Object。
我倾向于为标准类型的属性(字体、图片等)同时实现 Property Set 和 Property Let,但语义不同。通常在 Property Let 中,我会执行 "深拷贝",即克隆 StdFont 而不仅仅保留对原始对象的引用。

假设您对于一个对象类型都有Property SetProperty Let,并且假设实现代码相同(就像您的示例一样),当开发人员调用任一属性时,VB6是否有任何内置差异?例如,如果开发人员调用Let属性,VB6是否会隐式地决定突然按值而不是按引用传递对象,或者是否有其他类似的小细节?(我知道您说您喜欢编写具有单独语义的内容,但我不确定语言本身是否会有任何不同。) - Panzercrisis
在VB6中,参数没有“按值传递对象”的选项。使用ByVal oValue As StdPictureByRef oValue As StdPicture会改变对象引用传递的方式。这就像C/C++中的StdPicture *oValueStdPicture **oValue——始终是指针,但在第二种情况下,可以在过程内更改引用(例如将引用分配给新对象),并且调用者可以接收此新引用。因此,并没有“复制”选项,我通常在Property Let内部使用Clone方法(例如在IFont接口上)手动实现“深度复制”语义。 - wqw
对于引用类型,我指的是像在VB.NET/C#中按值传递引用。 - Panzercrisis
自从阅读并需要深度复制集合和类实例时,我采纳了@wqw的最后两段话作为我的个人编码规则;它可以轻松地区分指针和克隆,一目了然,非常方便。 - Marcelo Scofano Diniz

4

Property Set 用于对象类型的变量(ByRef),而 Property Let 用于值类型的变量(ByVal)。


2
这不是ByRef vs. ByVal问题,而是严格用于将对象引用返回给调用者。 - Bob77
确实,这不是ByRef/ByVal问题。但它用于将对象引用返回给调用者。为此,您使用 Property Get,就像返回任何其他类属性一样(没有专门用于返回类属性的对象特定版本)。 - mwolfe02
是的,我完全搞错了,这是用于分配给对象属性的 - 嗯,那真是个糟糕的错误。 - Bob77

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接