Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Mohammad Hamdy Ghanem
    @VBAndCs
    @paul1956 They will not allow to fix this! We had this conversation before dotnet/vblang#512
    and they closed the issue. I commented today, and cyrus gave me the same argument . Seee last comments
    I just reported this. It happens in WPF for both languages on both frameworks. Seems tuple are not yet fully supported in many frameworks! dotnet/wpf#3631
    rskar-git
    @rskar-git
    @AnthonyDGreen Just noticed your twitter acct "ThatVBGuy" (https://twitter.com/ThatVBGuy) is closed. Hoping all is well.
    Jeff Bowman
    @InteXX
    He's probably scaling back a bit. One of his lamentations has been the flood of communications he's been receiving. | @rskar-git
    Good question. I don't know. I'm taking stakx's word for it. He may be interested in discussing it: https://github.com/moq/moq4/issues/1067#issuecomment-706671833 | @paul1956
    Paul M Cohen
    @paul1956

    I am looking to put a proposal to VB to get some pattern support that fits within the guidelines of what enhancements VB language can get. The first is the declaration pattern. To address the patterns below

    Select Case x
        Case TypeOf x is Something
            Dim y as Something = x
        Case TypeOf x is SomethingElse
            Dim z as SomethingElse = x
    End Select
    
    If   TypeOf x is Something then
            Dim y as Something = x
    End if

    What I need to complete it is a VB like syntax that works for both and is extensible. If should be clear for any programmer that can read VB what is happening.

    Paul M Cohen
    @paul1956
    I would like to use dotnet/vblang#541 as a starting point but it is all over the place. I don't know if it is better to start again or clean it up.
    Mohammad Hamdy Ghanem
    @VBAndCs
    A new thread would be better.
    rskar-git
    @rskar-git
    Looks like twitter acct "ThatVBGuy" (https://twitter.com/ThatVBGuy) has returned!
    Mohammad Hamdy Ghanem
    @VBAndCs
    I am stumbling in minor VB editor issues like this dotnet/roslyn#48745
    Syrus always asks me to contribute a fix, and I have no knowledge nor time. If any of you want to participate, Cyrus will walk him through. It will be a valuable knowledge to build upon later if we forked the language.
    And it will be a good thing to start up with a stable bug-free VB version.
    Mohammad Hamdy Ghanem
    @VBAndCs
    why this is allowed:
    Call New PayCheckWnd().ShowDialog()
    but not this:
    New PayCheckWnd().ShowDialog()
    Adam Speight
    @AdamSpeight2008
    @VBAndCs Do it work if you but parenthesis around the new eg. (New PayCheckWnd()).ShowDialog
    Mohammad Hamdy Ghanem
    @VBAndCs
    @AdamSpeight2008 No. VB doesn't allow expressions to start with (
    @rskar-git Thanks. I am asking why. What prevents VB from allowing that?. What makes it risky to be allowed?
    Jeff Bowman
    @InteXX
    "VB doesn't allow expressions to start with (" Hm, that's odd. I do it frequently: oErrors.AddRange((Await Me.RoleManager.CreateAsync(oCity, oRole)).Errors). Do you find this to be an unexpected quirk? | @VBAndCs
    rskar-git
    @rskar-git
    @InteXX (and @VBAndCs) That doesn't really compare, Await got implemented as both an operator and a statement. On a technicality, your example begins with oErrors... - i.e. the letter "o" and not "(". In that example, Await is an operator, forming an expression which then returns an object that (presumably) has a member named Errors, which in turn gets invoked and returns something that becomes the parameter to the AddRange member of oErrors. While the distinctions between "statement" and "expression" tend to get fuzzy in real programming languages (e.g. https://therenegadecoder.com/code/the-difference-between-statements-and-expressions/), in at least the academic sense the differences are meaningful, and some languages enforce this dichotomy more sharply. E.g., C/C++ are super fuzzy, yet Java (although leveraging C/C++ idioms) is decidedly restrictive (and C# follows these Java restrictions).
    @VBAndCs I think the short answer here is that VB (in the VBA/VB6 days) never allowed a naked New expression to be a statement, and I guess nobody saw a compelling reason to then allow it in the VB.NET design. I do not understand why anything like new some_type(); or new some_type().someMethod(); is a good coding pattern, but I guess the C++ folks have liked it well enough (for whatever reasons of their own) that the Java designers allowed it.
    @VBAndCs However, I do not find the workarounds to do something like new some_type(); or new some_type().someMethod(); in VB.NET to be anything terrible or atrocious or particularly wasteful.
    rskar-git
    @rskar-git
    @InteXX and @VBAndCs In reading opinions elsewhere, it seems that a "statement" must be about (at least) one of two things: (1) effects how the executions flow (e.g. loops and go-tos); (2) will (likely) cause a side-effect (e.g. creation of a new instance or change in state of an instance). Perhaps there are other reasons (e.g. Imports and Namespace come to mind). The Java docs say (simply), FWIW: "Statements are roughly equivalent to sentences in natural languages. A statement forms a complete unit of execution."
    Cory Smith
    @DualBrain

    @VBAndCs I believe the reason why it works with CALL is that you are essentially passing an expression result (hidden variable) to a function (CALL) - without the CALL keyword, the code appears invalid syntax. Some of this harkens back to the original days of BASIC where each instruction (line) consists of "instruction number, an operation, and an operand." (Quoted from the original BASIC manual circa 1964.) Obviously we eventually moved away from including the instruction number... but the operation and operand pattern actually makes perfect sense. The confusion regarding this very valid pattern came into play when personal computers (due to lack of memory) added the ability to drop the LET keyword - however, it can be argued that it is simply inferred. Anyway the general concept for BASIC is each statement starts with a keyword (except, of course, for variable assignment - one reason why I'd like to see LET return, at least as an option for teaching beginners) - and although New is a keyword... it's really about creating a new variable... thus not a keyword in the sense of the accepted pattern (IMO). I would add that in the specific example, you could also do the following:

    If (New PayCheckWnd).ShowDialog = OK Then
    ...
    End If

    But again... I'm basically creating a throw-away variable as part of an expression... not a direct non-keyword command.

    Cory Smith
    @DualBrain
    As to the question regarding the difference between this channel and the Language one... this one is for any conversation regarding VB as well as all related subjects (XAML, Xamarin, WebAssembly, .NET, etc.) where the Language channel is really about discussing specific topics as they relate to the VB language design and compiler (language in -> "binary" out).
    Obviously that conversation could indeed be done in this channel. ;-)
    rskar-git
    @rskar-git
    @VBAndCs "[Regarding 'naked' new] What makes it risky to be allowed?" C++ has the (recently introduced) "discarded value" warning - see https://en.cppreference.com/w/cpp/language/attributes/nodiscard and https://softwareengineering.stackexchange.com/questions/363169/whats-the-reason-for-not-using-c17s-nodiscard-almost-everywhere-in-new-c . In my salad days (late-1980's), when Pascal was the reigning "school" language at most colleges, I and a co-worker were tasked to troubleshoot a reporting system written in C (by outside contractors). We (I and co-worker) were well versed in BASIC and Fortran, but only a smattering of C. In Pascal and QuickBASIC and Fortran, parentheses are not required where a function takes no parameters. In C, failing to place parentheses immediately after the function's name does not result in a call, but in a "naked" expression which results in a reference (or pointer) to the function. So Pascal-trained programmers made a bug, they forgot to put in the required parentheses, because in the other language they better knew a parameter-less call does not require them. But in C, we got a "discarded value", an expression which did nothing, which was legal syntax, and the compiler issued no warning. Perhaps there were C "linters" that might have caught it, but we certainly did not have one (and apparently neither did the contractors). It took us several days (via print statements to log files) to track it down. This sort of problem happened in a few place, in source code that spanned over 500,000 lines.
    Linter in the software sense: https://en.wikipedia.org/wiki/Lint_(software)
    rskar-git
    @rskar-git
    Anyway, the very fact that C++ programmers see value in having "discarded value" warnings, which includes new operations, indicates there are moments that something like new some_type(); can be a problem. Not sure about new some_type().someMethod(); though - but then the VB compiler is designed with the expectation of somehow recognizing what sort of statement is being expressed as early as possible.
    Mohammad Hamdy Ghanem
    @VBAndCs
    Thanks all for this helpful discussion .
    Let's stick with Call New :)
    Paul M Cohen
    @paul1956
    Why can’t you add an NewExpressionStatementSyntax which is New Keyword followed by expression? I think creating an ExpressionStatementSyntax the same as c# may have parsing issues.
    Mohammad Hamdy Ghanem
    @VBAndCs
    I cam up with a solution to Flags issues. I created a custom Flag class, and made an app to auto generate such flags. https://github.com/VBAndCs/VB-Flag-auto-generator
    The idea came to me after I auto generated enums for Ring Language witch doesn't support them.
    It is also like what the compiler does with the generics. And since Numeric types doesn't have a constraint to support generics, the only solution is to auto-generate the flag class.
    Mohammad Hamdy Ghanem
    @VBAndCs
    The bad thing is that I couldn't even use a base class to contain all the methods, because there is no way to cast the base class to the driven class!
    So, I put all the stuff in one big happy class that does many flag operations.
    Mohammad Hamdy Ghanem
    @VBAndCs

    I hope someday VB adds a flag block:

    Flag Foo
    
    End Flag

    The compiler can use my generator to generate the flag class.
    Maybe someone of the community can experiment with that.

    Paul M Cohen
    @paul1956
    Why not Flag Attribuate with
        Public Module EnumExtensions
    
            Private Sub CheckIsEnum(Of T)(withFlags As Boolean)
                If Not GetType(T).IsEnum Then
                    Throw New ArgumentException(String.Format(Globalization.CultureInfo.InvariantCulture, "Type '{0}' is not an enum", GetType(T).FullName))
                End If
                If withFlags AndAlso Not Attribute.IsDefined(GetType(T), GetType(FlagsAttribute)) Then
                    Throw New ArgumentException(String.Format(Globalization.CultureInfo.InvariantCulture, "Type '{0}' doesn't have the 'Flags' attribute", GetType(T).FullName))
                End If
            End Sub
    
            <Extension>
            Public Function ClearFlags(Of T As Structure)(value As T, flags As T) As T
                Return value.SetFlags(flags, False)
            End Function
    
            <Extension>
            Public Function ClearFlags(Of T As Structure)(value As T) As T
                CheckIsEnum(Of T)(withFlags:=True)
                For Each flag As T In [Enum].GetValues(GetType(T)).Cast(Of T)()
                    value = value.ClearFlags(flag)
                Next flag
                Return value
            End Function
    
            <Extension>
            Public Function CombineFlags(Of T As Structure)(flags As IEnumerable(Of T)) As T
                If flags Is Nothing Then
                    Throw New ArgumentNullException(NameOf(flags))
                End If
                CheckIsEnum(Of T)(withFlags:=True)
                Dim lValue As Long = 0
                For Each flag As T In flags
                    Dim lFlag As Long = Convert.ToInt64(flag, Globalization.CultureInfo.InvariantCulture)
                    lValue = lValue Or lFlag
                Next flag
                Return DirectCast([Enum].ToObject(GetType(T), lValue), T)
            End Function
    
            <Extension>
            Public Function GetDescription(Of T As Structure)(value As T) As String
                CheckIsEnum(Of T)(withFlags:=False)
                Dim name As String = [Enum].GetName(GetType(T), value)
                If name IsNot Nothing Then
                    Dim field As FieldInfo = GetType(T).GetField(name)
                    If field IsNot Nothing Then
                        Dim attr As DescriptionAttribute = TryCast(Attribute.GetCustomAttribute(field, GetType(DescriptionAttribute)), DescriptionAttribute)
                        If attr IsNot Nothing Then
                            Return attr.Description
                        End If
                    End If
                End If
                Return Nothing
            End Function
    
            <Extension>
            Public Iterator Function GetFlags(Of T As Structure)(value As T) As IEnumerable(Of T)
                CheckIsEnum(Of T)(withFlags:=True)
                For Each flag As T In [Enum].GetValues(GetType(T)).Cast(Of T)()
                    If value.IsFlagSet(flag) Then
                        Yield flag
                    End If
                Next flag
            End Function
    
            <Extension>
            Public Function IsFlagSet(Of T As Structure)(value As T, flag As T) As Boolean
                CheckIsEnum(Of T)(withFlags:=True)
                Dim lValue As Long = Convert.ToInt64(value, Globalization.CultureInfo.InvariantCulture)
                Dim lFlag As Long = Convert.ToInt64(flag, Globalization.CultureInfo.InvariantCulture)
                Return (lValue And lFlag) <> 0
            End Function
    
            <Extension>
            Public Function SetFlags(Of T As Structure)(value As T, flags As T, [on] As Boolean) As T
                CheckIsEnum(Of T)(withFlags:=True)
                Dim lValue As Long = Convert.ToInt64(value, Globalization.CultureInfo.InvariantCulture)
                Dim lFlag As Long = Convert.ToInt64(flags, Globalization.CultureInfo.InvariantCulture)
                If [on] Then
                    lValue = lValue Or lFlag
                Else
                    lValue = lValue And (Not lFlag)
                End If
                Return DirectCast([Enum].ToObject(GetType(T), lValue), T)
            End Function
    
            <Extension>
            Public Function SetFlags(Of T As Structure)(value As T, flags As T) As T
                Return value.SetFlags(flags, True)
            End Function
    
        End Module
    This would be easy to put in a NuGet with some samples and tests
    Mohammad Hamdy Ghanem
    @VBAndCs

    What's wrong with System.Enum
    1.Nearly all of Enum's static methods are non-generic leading to the following issues. ◦Requires the enum type to be explicitly specified as an argument and requires invocation using static method syntax such as Enum.IsDefined(typeof(ConsoleColor), value) instead of what should be value.IsDefined().
    ◦Requires casting/unboxing for methods with an enum return value, eg. ToObject, Parse, and GetValues.
    ◦Requires boxing for methods with enum input parameters losing type-safety, eg. IsDefined and GetName.

    2.Support for flag enums is limited to just the HasFlag method which isn't type-safe, is inefficient, and is ambiguous as to whether it determines if the value has all or any of the specified flags. It's all by the way.
    3.Most of its methods use reflection on each call without any sort of caching causing poor performance.
    4.The pattern to associate extra data with an enum member using Attributes is not supported and instead requires users to manually retrieve the Attributes via reflection. This pattern is commonly used on enum members with the DescriptionAttribute, EnumMemberAttribute, and DisplayAttribute.

    I didn't look at his work, but I think using a standalone class will be easier and may perform better.
    Mohammad Hamdy Ghanem
    @VBAndCs
    This is a list of the members I added to the class, noting that the flag is immutable, and methods don't change its state, but return a new instance carring the result:
    Shared Fields:
    None
    All
    Shared Properties:
    Flags
    FlagNames
    FlagValues
    Instance Properties:
    Name
    OnFlags
    OffFlags
    Instance Methods:
    ToString()
    ToString(separator)
    ToInteger
    SetFlags
    SetAllExcxept
    UnsetFlags
    UnsetAllExcxept
    ToggleFlags
    ToggleAllFlags()
    AreAllSet
    AreAllUnset
    AreAnySet
    AreAnyUnset
    And this is a sample of an auto-generated Flag:
    ```VB.NET
    Public Shared ReadOnly X As New MyFlag("X", 1)
    Public Shared ReadOnly Y As New MyFlag("Y", 2)
    Public Shared ReadOnly Z As New MyFlag("Z", 4)
    Const MaxValue As UInteger = 7
    Public Shared ReadOnly None As New MyFlag("None", 0)
    Public Shared ReadOnly All As New MyFlag("All", MaxValue)
    
    Private ReadOnly Value As UInteger
    
    Private Sub New(value As UInteger)
        Me.Value = If(value > MaxValue, MaxValue, value)
    End Sub
    
    Private Sub New(name As String, value As UInteger)
        _Name = name
        Me.Value = If(value > MaxValue, MaxValue, value)
    End Sub
    
    Public Shared ReadOnly Property Flags As MyFlag() = {X, Y, Z}
    Public Shared ReadOnly Property FlagNames As String() = {"X", "Y", "Z"}
    Public Shared ReadOnly Property FlagValues As UInteger() = {1, 2, 4}
    Public ReadOnly Property Name As String
    
    Public ReadOnly Property OnFlags As List(Of MyFlag)
        Get
            Dim lstFlags As New List(Of MyFlag)
            For Each flag In Flags
                If (Value And flag.Value) > 0 Then lstFlags.Add(flag)
            Next
            Return lstFlags
        End Get
    End Property
    
    Public ReadOnly Property OffFlags As List(Of MyFlag)
        Get
            Dim lstFlags As New List(Of MyFlag)
            For Each flag In Flags
                If (Value And flag.Value) = 0 Then lstFlags.Add(flag)
            Next
            Return lstFlags
        End Get
    End Property
    
    
    Public Overrides Function ToString() As String
        Return ToString("+")
    End Function
    
    Public Overloads Function ToString(Separator As String) As String
        If Value = 0 Then Return None.Name
        If Value = MaxValue Then Return All.Name
        Dim sb As New Text.StringBuilder
        For Each flag In Flags
            If (Value And flag.Value) > 0 Then
                If sb.Length > 0 Then sb.Append(Separator)
                sb.Append(flag.Name)
            End If
        Next
        Return sb.ToString
    End Function
    
    Public Function ToInteger() As UInteger
        Return Value
    End Function
    
    Public Function SetFlags(ParamArray flags() As MyFlag) As MyFlag
        If flags Is Nothing OrElse flags.Length = 0 Then Return Value
    
        Dim v = Value
        For Each flag In flags
            v = v Or flag.Value
        Next
        Return v
    End Function
    
    Public Function SetAllExcxept(ParamArray flags() As MyFlag) As MyFlag
        If flags Is Nothing OrElse flags.Length = 0 Then Return Value
    
        Dim v As UInteger = 0
        For Each flag In flags
            v = v Or flag.Value
        Next
        Return Value And Not v
    End Function
    
    
    Public Function UnsetFlags(ParamArray flags() As MyFlag) As MyFlag
        If flags Is Nothing OrElse flags.Length = 0 Then Return Value
    
        Dim v = Value
        For Each flag In flags
            v = v And Not flag.Value
        Next
        Return v
    End Function
    
    Public Function UnsetAllExcxept(ParamArray flags() As MyFlag) As MyFlag
        If flags Is Nothing OrElse flags.Length = 0 Then Return Value
    
        Dim v As UInteger = 0
        For Each flag In flags
            v = v Or flag.Value
        Next
        Return v
    End Function
    
    Public Function ToggleFlags(ParamArray flags() As MyFlag) As MyFlag
        If flags Is Nothing OrElse flags.Length = 0 Then Return Value
    
        Dim v = Value
        For Each flag In flags
            v = v Xor flag.Value
        Next
    Mohammad Hamdy Ghanem
    @VBAndCs
    I also added IsSet(flag) , a default readonly property (Indexer) that returns true if the given flag is set.
    Mohammad Hamdy Ghanem
    @VBAndCs
    @paul1956 one additional benefit of my flag class is the ability to do this:
        flag += MyFlag.Y
        flag -= MyFlag.X
    This will not be safe with enums as you must check if the flag is set before subtracting, and unset before adding
    Cory Smith
    @DualBrain
    @VBAndCs Looking briefly at your flag project... looks very cool. Definately would like to see this as some sort of add-in to VS.