vblang
vblang copied to clipboard
Custom implicit Ctype is not used in dynamic mode
VB can't call the implicit ctype operator on dynamic objects. This code gives the runtime error: Can't convert from Test To String:
Option Strict Off
Option Explicit On
Module Program
Sub Main()
Dim o As Object = New Test
Dim s As String = o
End Sub
End Module
Class Test
Public Shared Widening Operator CType(t As Test) As String
Return t.ToString()
End Operator
End Class
While the same code runs correctly in C#:
dynamic o = new Test();
string s = o;
class Test
{
public static implicit operator string (Test t) => t.ToString();
}
I think Vb should adapt the C# spcs about this, after all vb was a dynamic langish since before .NET, where even declaring variables was not mandatort (Option Explicit Off was the default in old vb versions before dotnet.) Also, I suggest that dynamically or not, vb should use .ToString to implicitly convert any type to a string as lomg as ther is no a suitable CType defined to do that. This is more like how VB does things.
VB is stuck in limbo here: Object
really means System.Object
, and with Option Strict Off
, Object
does not become System.Dynamic.DynamicObject
, it stays a System.Object
. On that technicality, VB is aligned with C#. In C#, object
and dynamic
are seen as two distinct types. Hence, C# is able to bend the rules (in its own particular idiom) when its comes to implicit conversions of the dynamic
type, even as it will not do the same with object
.
Option Strict Off
lets VB apply its own peculiar set of rules to locate applicable members utilizing reflection (or COM IUnknown) when addressing references cast as Object
, as well as allowing for unrestricted casting at compile-time. It's done in a way to align with the idioms of Visual Basic 6 (and VBA, for that matter). In VB6 (& VBA), an Object
is a reference to an instance generated from an ActiveX (or COM) assembly which (usually) also implements the IUnknown interface; for all other things, it has its Variant
. (For dynamic access of members of an ActiveX/COM Object
to work, the instance must implement IUnknown, a primitive form of reflection.) In VB.NET, with Option Strict Off
, its interpretation of Object
combines these VB6 idioms for Object
and Variant
together - .NET "boxing" replaces the role of Variant
. This approach was implemented as part of the VB.NET language and compiler design long before System.Dynamic
was conceived and developed. (There was some talk and effort to transition VB.NET Object
from its own implementation towards System.Dynamic
, but that plan got scrapped. See https://www.infoq.com/news/2007/05/VBx/ and https://en.wikipedia.org/wiki/Visual_Basic_.NET#2010_(VB_10.0) )
In the grand scheme of things, this issue is a very minor annoyance. In practice, we VB'ers should stick with Option Strict On
, and only employ Option Strict Off
for those very rare moments where it may make sense. (And even then, I personally prefer to work through a wrapper, utilizing a private class and an interface, in accessing something dynamically. One could then implement implicit conversions as desired.)
there's a certain irony that for many years, the curly-bracket people derided VB because 'Variant' existed.
Then when they realise that a dynamic type is useful, VB gets derided for not having the 'new' flavour of 'Variant', now known as 'dynamic'.
@pricerc @rskar-git
I thing things are much simplier rhat that and the solution exists and is very cheap. I expect that the issue is that VB lowres the code to:
Dim s As String = CType(o, String)
But it should be lowerd to:
Dim s As String
Try
s = CType(o, String)
Catch ex As InvalidCastException
Try
s = CTypeDynamic(o, GetType(String))
Catch
Throw
End Try
Catch
Throw
End Try
And it will work perfectly.
@CyrusNajmabadi @KathleenDollard I think this is related to Roslyn now, and need no change in lang specs, as the language already provided the CTypeDynamic function, but seems it forgot to use it!
@VBAndCs if you think there is an issue in Roslyn, please file an issue there.
I think this is related to Roslyn now, and need no change in lang specs, as the language already provided the CTypeDynamic function, but seems it forgot to use it!
If you think the compiler is not behaving as per the spec, please make sure to link to the parts of the spec related to this and explain how the compiled code is not in line with it. Thanks!