Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Cory Smith
    @DualBrain
    Is there an existing Wiki somewhere that has a good starting point for HowTo's?
    Some examples include such work arounds related to "How can we use VB to build WebAssembly applications?" or "How can we use VB to build Xamarin applications?"
    rskar-git
    @rskar-git
    Emulation of C#-style "ref local". See https://docs.microsoft.com/en-us/dotnet/csharp/write-safe-efficient-code for background.
    ' Start off with a Console application project.
    
    ' Be sure these options are On:
    '     Option Strict On
    '     Option Infer On
    
    ' Imports:
    '     Imports System.Runtime.InteropServices
    
    Structure Xyz
        Dim x As Short
        Dim y As Integer
        Dim z As Long
        Dim u As Single
        Dim v As Double
    End Structure
    
    Sub Main()
    
        Dim pdq0 As Xyz
        Dim pdq1 As Xyz
        Dim pdq2 As Xyz
    
        ' Inferencing is the only way to have a properly typed
        ' variable of Span(Of Xyz).
        Dim refOf_Xyz = MemoryMarshal.CreateSpan(Of Xyz)(Nothing, 0)
    
        ' refOf_Xyz(0) is almost works like a Dim ByRef x As Xyz;
        ' a ref local, if you will.
        ' Alternative to refOf_Xyz(0) is MemoryMarshal.GetReference(refOf_Xyz).
    
        ' WARNING! VB can only be a consumer of ref types, and then 
        ' only by way of a ByRef parameter to function or lambda!
        ' Also, avoid directly using such in a With statement!
    
        ' Reference to pdq0
        refOf_Xyz = MemoryMarshal.CreateSpan(pdq0, 1)
        Call (Sub(ByRef x As Xyz) x.x = 1)(refOf_Xyz(0))
    
        ' Reference to pdq1
        refOf_Xyz = MemoryMarshal.CreateSpan(pdq1, 1)
        Call Sub(ByRef x As Xyz)
                 With x
                     .x = 2
                     .y = 3
                     .z = 4
                     .u = 1.234
                     .v = 987654321.12345684
                 End With
             End Sub(MemoryMarshal.GetReference(refOf_Xyz))
    
        ' Reference to pdq2
        refOf_Xyz = MemoryMarshal.CreateSpan(pdq2, 1)
        Call Sub(ByRef x As Xyz)
                 x.u = 2.468
                 x.v = 111222333444.55566
             End Sub(refOf_Xyz(0))
    
        ' Now examine pdq0, pdq1, and pdq2
        ' Confirm they have had their fields asssigned as expected.
        Stop
    
    End Sub
    rskar-git
    @rskar-git
    Folks have long desired for a way to use For Each upon a collection of Structure (a.k.a. value) types that allows for mutations (state changes) of such. Here is one straight-forward approach, which can be used on any object which implements IList(Of T) - a demonstration of the ByIndex extensions.
    ' Start off with a Console application project.
    
    ' Be sure these options are On:
    '     Option Strict On
    '     Option Infer On
    
    ' Imports:
    ' Imports System.Runtime.CompilerServices
    
    Structure Xyz
        Dim x As Short
        Dim y As Integer
        Dim z As Long
        Dim u As Single
        Dim v As Double
    End Structure
    
    Sub Main()
    
        Dim arrayOf_Xyz(9) As Xyz
    
        For Each item In arrayOf_Xyz.ByIndex
            ' item.List would be the IList(Of Xyz)
            ' item.Index is the index into the above IList
            ' item.Value is a property to item.List(item.Index);
            ' however, it is still stuck as a pass by value
            ' situation. Hence the use of a lambda, like so:
            Dim itemIndex = item.Index
            item.Call(Sub(ByRef x)
                          ' This is the only reliable way, in pure VB, 
                          ' short of somehow using Span(Of T), to get at
                          ' a reference to a Structure rather than its copy.
                          x.x = CShort(itemIndex And 3)
                          x.y = itemIndex And 7
                          x.z = (x.x * x.y) Xor itemIndex
                          x.u = CSng(itemIndex / 100)
                          x.v = itemIndex / 10
                      End Sub)
        Next
    
        ' Now examine elements in arrayOf_Xyz
        ' Confirm they have had their fields asssigned as expected.
        Stop
    
        For Each item In arrayOf_Xyz.ByIndex(2, 3)
            ' ByIndex can do ranges; here we start with arrayOf_Xyz(2)
            ' and loop through arrayOf_Xyz(2 + 3 - 1), i.e. arrayOf_Xyz(4).
            item.Call(Sub(ByRef x)
                          x.z *= 2
                          x.u *= 5
                      End Sub)
        Next
    
        ' Now examine elements in arrayOf_Xyz
        ' Confirm only indicies 2 through 4 have had their 
        ' fields asssigned as expected.
        Stop
    
        ' Note that item.Call can also take AddressOf some 
        ' applicable function.
        For Each item In arrayOf_Xyz.ByIndex(7)
            item.Call(AddressOf Foo)
        Next
    
        ' Now examine elements in arrayOf_Xyz
        ' Confirm only indicies 7 through 9 have had their 
        ' fields asssigned as expected.
        Stop
    
    End Sub
    
    Sub Foo(ByRef x As Xyz)
        x.v = 1 + Math.Sqrt(Math.Abs(x.v))
    End Sub

    Region "For Each ByIndex Extensions"

    Delegate Sub ByIndexAction(Of T)(ByRef Item As T)
    Structure ByIndexItem(Of T)
        Public ReadOnly List As IList(Of T)
        Public ReadOnly Index As Integer
        Public Sub New(List As IList(Of T), Index As Integer)
            Me.List = List
            Me.Index = Index
        End Sub
        Sub [Call](Action As ByIndexAction(Of T))
            Action(List(Index))
        End Sub
        Public Property Value As T
            Get
                Return List(Index)
            End Get
            Set(value As T)
                List(Index) = value
            End Set
        End Property
    End Structure
    <Extension> Iterator Function ByIndex(Of T)(List As IList(Of T)) _
        As IEnumerable(Of ByIndexItem(Of T))
        For i As Integer = 0 To List.Count - 1
            Yield New ByIndexItem(Of T)(List, i)
        Next
    End Function
    <Extension> Iterator Function ByIndex(Of T)(List As IList(Of T), Start As Integer) _
        As IEnumerable(Of ByIndexItem(Of T))
        If Start < 0 OrElse Start >= List.Count Then Exit Function
        For i As Integer = Start To List.Count - 1
            Yield New ByIndexItem(Of T)(List, i)
        Next
    End Function
    <Extension> Iterator Function ByIndex(Of T)(List As IList(Of T),
                                                Start As Integer, Length As Integer) _
        As IEnumerable(Of ByIndexItem(Of T))
        If Start < 0 OrElse Start >= List.Count Then Exit Function
        If Length <= 0 OrElse (Start + Length) > List.Count Then Exit Function
        For i As Integer = 0 To Length - 1
            Yield New ByIndexItem(Of T)(List, Start + i)
        Next
    End Function

    End Region

    rskar-git
    @rskar-git
    This is a somewhat shady, but likely safe enough, approach to process through an array (note, must be an array!) of Structure (a.k.a. value) types. Utilizing the Enumerator of Span(Of T), this is a handy way to access the array elements in a memory efficient manner, and allows for mutations (state changes). The hitch is one must work through a Delegate (such as a lambda or AddressOf function).
    ' Start off with a Console application project.
    
    ' Be sure these options are On:
    '     Option Strict On
    '     Option Infer On
    
    ' Imports:
    ' Imports System.Runtime.CompilerServices
    ' Imports System.Runtime.InteropServices
    
    Structure Xyz
        Dim x As Short
        Dim y As Integer
        Dim z As Long
        Dim u As Single
        Dim v As Double
    End Structure
    
    Sub Main()
    
        Dim arrayOf_Xyz(9) As Xyz
    
        Dim itemOrdinal = -1
        arrayOf_Xyz.ForEachByRef(
            Sub(ByRef x)
                ' ByRef parameter of lambda or function:
                ' This is the only way in VB to dereference a Span(Of Xyz),
                ' and get at a reference to a Structure rather than its copy.
                itemOrdinal += 1
                x.x = CShort(itemOrdinal And 3)
                x.y = itemOrdinal And 7
                x.z = (x.x * x.y) Xor itemOrdinal
                x.u = CSng(itemOrdinal / 100)
                x.v = itemOrdinal / 10
            End Sub)
    
        ' Now examine elements in arrayOf_Xyz
        ' Confirm they have had their fields asssigned as expected.
        Stop
    
        arrayOf_Xyz.ForEachByRef(2, 3,
            Sub(ByRef x)
                ' ForEachByRef can do slices; here we start with arrayOf_Xyz(2)
                ' and loop through arrayOf_Xyz(2 + 3 - 1), i.e. arrayOf_Xyz(4).
                x.z *= 2
                x.u *= 5
            End Sub)
    
        ' Now examine elements in arrayOf_Xyz
        ' Confirm only indicies 2 through 4 have had their 
        ' fields asssigned as expected.
        Stop
    
        arrayOf_Xyz.ForEachByRef(2, 3,
            Sub(ByRef x)
                ' ForEachByRef can do slices; here we start with arrayOf_Xyz(2)
                ' and loop through arrayOf_Xyz(2 + 3 - 1), i.e. arrayOf_Xyz(4).
                x.z *= 2
                x.u *= 5
            End Sub)
    
        ' Now examine elements in arrayOf_Xyz
        ' Confirm only indicies 2 through 4 have had their 
        ' fields asssigned as expected.
        Stop
    
        ' Note that ForEachByRef can also take AddressOf some 
        ' applicable function.
        arrayOf_Xyz.ForEachByRef(7, AddressOf Foo)
    
        ' Now examine elements in arrayOf_Xyz
        ' Confirm only indicies 7 through 9 have had their 
        ' fields asssigned as expected.
        Stop
    
    End Sub
    
    Sub Foo(ByRef x As Xyz)
        x.v = 1 + Math.Sqrt(Math.Abs(x.v))
    End Sub

    Region "ForEachByRef Extensions"

    Delegate Sub ForEachAction(Of T As Structure)(ByRef Item As T)
    <Extension> Sub ForEachByRef(Of T As Structure)(
        Array As T(),
        Action As ForEachAction(Of T))
        With Array.AsSpan().GetEnumerator()
            Do While .MoveNext()
                Action(.Current)
            Loop
        End With
    End Sub
    <Extension> Sub ForEachByRef(Of T As Structure)(
        Array As T(),
        Start As Integer,
        Action As ForEachAction(Of T))
        With Array.AsSpan().Slice(Start).GetEnumerator()
            Do While .MoveNext()
                Action(.Current)
            Loop
        End With
    End Sub
    <Extension> Sub ForEachByRef(Of T As Structure)(
        Array As T(),
        Start As Integer,
        Length As Integer,
        Action As ForEachAction(Of T))
        With Array.AsSpan().Slice(Start, Length).GetEnumerator()
            Do While .MoveNext()
                Action(.Current)
            Loop
        End With
    End Sub
    <Extension> Sub ForEachByRef(Of T As Structure)(
        List As IList(Of T),
        Action As ForEachAction(Of T))
        Dim itemSize As Integer = Marshal.SizeOf(Of T)()
        For index As Integer = 0 To List.Count - 1
            Dim itemSpan = MemoryMarshal.CreateSpan(List(index), itemSize)
            Action(itemSpan(0))
        Next
    End Sub
    <Extension> Sub ForEachByRef(Of T As Structure)(
        List As IList(Of T),
        Start As Integer,
        Action As ForEachAction(Of T))
        If Start < 0 Then Exit Sub
        Dim itemSize As Integer = Marshal.SizeOf(Of T)()
        For index As Integer = Start To List.Count - 1
            Dim itemSpan = MemoryMarshal.CreateSpan(List(index), itemSize)
            Action(itemSpan(0))
        Next
    End Sub
    <Extension> Sub ForEachByRef(Of T As Structure)(
        List As IList(Of T),
        Start As Integer,
        Length As Integer,
        Action As ForEachAction(Of T))
        If Start < 0 Then Exit Sub
        If Length <= 0 Then Exit Sub
        Dim itemSize As Integer = Marshal.SizeOf(Of T)()
        For index As Integer = Start To Start + Length - 1
            Dim itemSpan = MemoryMarshal.CreateSpan(List(index), itemSize)
            Action(itemSpan(0))
        Next
    End Sub

    End Region

    rskar-git
    @rskar-git
        ' Modifying array of string with ByIndex
        Dim abc = {"A", "B", "C"}
        For Each item In abc.ByIndex
            item.Value += "Z"
        Next
        Stop ' Now abc is { "AZ", "BZ", "CZ" }
    Paul M Cohen
    @paul1956
    Is there a way to split the code (non Shared) in a Form into 2 files. My main form Form1 is huge and very difficult to work with. I have Regions for each group of functionality but I would like to move these to into 1 or more files. If I create another file and set it to "Partial Public Class Form1" it gets created as a new Form with its own designer and Resx file but can access all the things it needs from Form1, if you select open designer it opens it own designer . The original form does not need to access anything in the new form. The new form just has events handlers and private functions. If that is impossible what about just the private functions in a helper file. The private functions access items on Form1.
    Cory Smith
    @DualBrain
    @paul1956 I believe you are running into what I would consider a "bug" in the IDE. If you were to do this outside of VS, I believe it would work as you were thinking... but in VS, it tries to "do more" and that "more" is wrong. Incidentially, I do exactly what you are doing all the time... especially when I'd like to keep everyting Option Strict On (in the main form file) but have a partial form file that contains the Option Strict Off functionality. I do it this way so that it is still internal to the form... not some module or class where it could potentially be seen (or rather used).
    Meaning, if you don't double-click on it... only use the "view code" functionality... it should work like you are expecting - and just be OK with the fact that the occasional double-click will occur where you see a "blank form"... immediately close out of that (not saving it) and be "OK" with it. ;-)
    Paul M Cohen
    @paul1956
    Yea I see it works as long as you don't double click. I will report it.
    Paul M Cohen
    @paul1956
    @DualBrain I sent feedback you might want to add use cases and up vote it.
    Cory Smith
    @DualBrain
    NOTE - Please do not post in this room for the foreseeable future. Leaving open so that the content isn't lost; but please continue and/or add to the conversation in the https://gitter.im/VB-NET/community room. If you haven't joined that room, please do so.