38

I have just created several Property Set methods, and they didn't compile. When I changed them to Property Let, everything was fine.

I have since studied the documentation to find the difference between Property Set and Property Let, but must admit to being none the wiser. Is there any difference, and if so could someone offer a pointer to a proper explanation of it?

essential
  • 349
  • 3
  • 16
Brian Hooper
  • 20,414
  • 23
  • 82
  • 132

3 Answers3

34

Property Set is for objects (e.g., class instances)

Property Let is for "normal" datatypes (e.g., string, boolean, long, etc.)

mwolfe02
  • 22,236
  • 8
  • 78
  • 132
  • It is unrelated to WithEvents, it is for returning object references as properties. There are many times when you want to do this, most often when you have any kind of object hierarchy. – Bob77 Feb 18 '11 at 15:29
  • Wrong. `Property Get` is used for returning object references as properties, not `Property Set`. – mwolfe02 Feb 18 '11 at 16:02
  • http://msdn.microsoft.com/en-us/library/aa266202(VS.60).aspx: Like a `Function` and `Property Get` procedure, a `Property Set` procedure is a separate procedure that can take arguments, perform a series of statements, and change the value of its arguments. **However, unlike a `Function` and `Property Get` procedure, both of which return a value, you can only use a `Property Set` procedure on the left side of an object reference assignment (`Set` statement).** – mwolfe02 Feb 18 '11 at 16:12
  • +1 Correct that `Property Set` defines a property that can be used on the left hand side of a `Set` statement. I do think the mention of `WithEvents` is a bit confusing though, it's not really related to explaining the difference. `Property Set` can be useful for 1:1 relationships between objects that can be changed dynamically at runtime, i.e. beyond `WithEvents`. – MarkJ Feb 18 '11 at 17:09
  • 3
    Yes, for "setting" a property - I had this 180 degrees backwards, mea culpa. In the end it's as simple as reading the manual as pointed out above. – Bob77 Feb 18 '11 at 17:52
  • @Bob: +1 for admitting a mistake. I apologize if my tone came across as harsh, but I wanted to clear up the technical issue. And while we're issuing mea culpas, I'll admit my original wording unnecessarily confused the issue of `Property Set` and `WithEvents`. When I was first learning about classes in VB6/VBA I had trouble understanding when you would want to use the `Property Set` statement. I simply wanted to provide the OP with a common example. To suggest it was the 'only' situation where `Property Set` would be useful was a mistake on my part. Hopefully the new wording is clearer. – mwolfe02 Feb 18 '11 at 20:21
28

Property Let is more versatile than Property Set. The latter is restricted to object references only. If you have this property in a class

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

You can call Property Set Picture with

Set oObj.Picture = Me.Picture

You can call Property Let Picture with both

Let oObj.Picture = Me.Picture
oObj.Picture = Me.Picture

Implementing Property Set is what other developers expect for properties that are object references but sometimes even Microsoft provide only Property Let for reference properties, leading to the unusual syntax oObj.Object = MyObject without Set statement. In this case using Set statement leads to compile-time or run-time error because there is no Property Set Object implemented on oObj class.

I tend to implement both Property Set and Property Let for properties of standard types -- fonts, pictures, etc -- but with different semantics. Usually on Property Let I tend to perform "deep copy", i.e. cloning the StdFont instead of just holding a reference to the original object.

wqw
  • 10,921
  • 1
  • 30
  • 39
  • Assuming you have both `Property Set` and `Property Let` for an object type, and assuming the implementing code is the same (like in your example), does VB6 have any built-in difference in what it'll actually do when the developer calls either property? For instance, will VB6 implicitly decide to suddenly pass the object by value, instead of by reference, if the developer calls the `Let` property, or are there any other little nuances like that? (I know you said the ones you like to write have the separate semantics, but I'm not sure if the language does anything different on its own.) – Panzercrisis Jul 10 '17 at 18:25
  • In VB6 there is no "pass the object by value" option for params. Using `ByVal oValue As StdPicture` vs `ByRef oValue As StdPicture` changes the way the object *reference* is passed. It's like `StdPicture *oValue` vs `StdPicture **oValue` in C/C++ -- always pointers but in the second case one has the ability to change the *reference* (e.g. assign ref to a new object) inside the procedure and the caller can receive this new reference. So there is no "copy" option per se and I'm usually using `Clone` method (e.g. on `IFont` interface) inside `Property Let` to manually impl "deep copy" semantics. – wqw Jul 20 '17 at 07:16
  • For reference types, I mean passing the reference by value, like in VB.NET/C#. – Panzercrisis Jul 20 '17 at 13:43
  • I adopted @wqw's two last paragraphs as my personal coding rule since I read it and had the need of deep copy Collections and Class instances; it facilitates too much on a glance know if it's only a pointer or a clone... – Marcelo Scofano Diniz Aug 22 '20 at 22:50
4

Property Set is for object-like variables (ByRef) whereas Property Let is for value-like variables (ByVal)

Foo Bah
  • 23,255
  • 5
  • 49
  • 78
  • 2
    It isn't a ByRef vs. ByVal issue, but is strictly used for returning object references to the caller. – Bob77 Feb 18 '11 at 15:30
  • It's true that it's not a ByRef/ByVal issue. But it is **not** used for returning object references to the caller. For that you use `Property Get` the same as you would for returning any other class property (there is no object-specific version for returning class properties). – mwolfe02 Feb 18 '11 at 16:20
  • Yes, I had that exactly backwards, it's for assigning to an object property - duh, really bad goof there. – Bob77 Feb 18 '11 at 17:49