Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom implicit Ctype is not used in dynamic mode #613

Open
VBAndCs opened this issue Feb 1, 2022 · 4 comments
Open

Custom implicit Ctype is not used in dynamic mode #613

VBAndCs opened this issue Feb 1, 2022 · 4 comments

Comments

@VBAndCs
Copy link

VBAndCs commented Feb 1, 2022

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.

@rskar-git
Copy link

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.)

@pricerc
Copy link

pricerc commented Feb 25, 2022

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'.

@VBAndCs
Copy link
Author

VBAndCs commented Mar 3, 2022

@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!

@CyrusNajmabadi
Copy link
Member

@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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants