Mike_D
(Mike D)
July 17, 2025, 7:42pm
1
Given this Method in a Module:
Public Function ToBytesVariant(extends v as Variant) As Uint8()
[...]
End Function
Should I be able to call it using a normal (non-extension) syntax?
var v as variant = "foobar"
var bytes() as uint8
bytes = v.ToBytesVariant() // this compiles
bytes = ToBytesVariant(v) // this does not compile
The second version does not compile, and the error message is weird:
Extension method Module1.ToBytesVariant requires a conversion from class Window1.Window1 to type Variant; use CType to explicitly convert first
Is this
a bug in the compiler, where calling an Extension method without using Extension syntax should be allowed, but is failing?
a bug in the compiler, where calling an Extension method without using Extension syntax is not allowed, and the error message is wrong?
No, extends means that you have to prefix the class before the method, ie your first syntax. That’s the point of it.
Mike_D
(Mike D)
July 17, 2025, 7:46pm
3
So I think you are picking option two?
I notice that if I try a third way:
bytes = Module1.ToBytesVariant(v)
I get another error message
Static reference to extension method: call this on a value of type Variant.
the error message is more clear.
Agreed, the first error is not clear at all. That one is much better. I think I have a bug report for that. Let me see.
No it was a different but similar issue, which is now closed:
Delegate defined with an Assigns parameter results in a baffling error message
https://tracker.xojo.com/xojoinc/xojo/-/issues/64376
I’m not getting an error here. This is my toBytes function definition in a module:
Public Function toBytes(extends v as Variant) As UInt8()
...
End Function
Then using as:
var v as Variant = "Test"
var result() as UInt8 = v.toBytes
I do note that your function is named VariantToBytes but you’re trying to call a function named ToBytesVariant.
1 Like
The problem is when you try and do:
var v as Variant = "Test"
var result() as UInt8 = toBytes( v )
But why would you? It’s an extends method.
1 Like
Mike_D
(Mike D)
July 17, 2025, 8:00pm
8
Sorry, that was a typo. Fixed.
I’ve submitted this as Extension method - confusing compiler error message
To get around that, you need a separate definition:
Public Function toBytes(extends v as Variant) As UInt8()
...
End Function
Public Function toBytes(v as Variant) As UInt8()
return v.toBytes
End Function
3 Likes
Mike_D
(Mike D)
July 17, 2025, 8:03pm
10
Right, if it’s not allowed, the compiler message should be sensible.
I think it’s just giving the best it can because you’re doing something you shouldn’t be and it probably hasn’t come up a lot before without people realizing and correcting their issue. A better message would be a great idea, though, and I’ll toss a thumbs up on your case. Be sure you do the same.
Agreed, always thumbs up your own bugs if they are affecting you. It helps to boost the priority of a fix. +1 from me.
The error message is worded like it is because, in the context of Window1, these two lines of code are equivalent.
bytes = ToBytesVariant(v)
bytes = Self.ToBytesVariant(v)
Self is simply implied due to the context, just like you can do either of these to change the window width.
Width = 500
Self.Width = 500
I do agree that the wording is confusing, but I’m not sure how they could fix that since it’s technically correct.
3 Likes
Mike_D
(Mike D)
July 17, 2025, 8:59pm
14
Interesting point about “Self” - in fact, this code:
bytes = Self.ToBytesVariant
gives the exact same error message.
And this code:
bytes = ToBytesVariant(v)
in the context of a Module method (not a Window method), does not give the weird error message.
So I think you are right, it’s the implied “Self” in all window methods which is confusing the compiler here. Fun!
1 Like
Mike_D
(Mike D)
July 17, 2025, 9:05pm
15
I stumbled upon this because I had a vague sense that you could always call extension methods with or without the dot notation, e.g.
dim s as string
dim n as integer
n = s.LenB()
n = LenB(s)
but in hindsight, I think this was just a feature of the API, where some functions such as LenB are defined with both method signatures.
That’s what led me to think this was a general property of Extension methods.
The n = LenB(s) requires the method to be defined with an Assigns parameter, where the s.LenB requires an Extends parameter.
I don’t remember if you can do an Assigns signature in a module method, but I would think so.
It’s not an Assigns method. An Assigns method would allow you to say:
Method LenB( s as String, assigns x as Integer ) // Allows:
LenB(s) = 10
(s as a standard parameter, 10 in x as an assigns)
Method LenB( Extends s as String, assigns x as Integer ) // Allows:
s.LenB = 10
(s via extends, 10 in x via assigns)
Method LenB( Extends s as String ) as Integer // Allows:
variable = LenB( s )
Method LenB( Extends s as String ) as Integer // Allows:
variable s.LenB
Yup, you’re right. Shows you how much I use Assigns…
They can be very nice for code readability.
Mike_D
(Mike D)
July 17, 2025, 9:56pm
20
I notice that in API2, this “dual use” doesn’t exist:
// API2
var s as string
var n as integer
n = s.Length() // OK
n = Length(s) // Error: There is more than one method with this name but this does not match any of the available signatures.