referencing VisualBasic methods - vb.net

In VB, I want to assign a (shared) method to a variable
And I'm asking if there is some namespace operator like :: in C++ and Java
Class C
Public Shared Function m(a as Integer) as Integer
Return a * 2
End Function
End Class
Public Sub Main()
Dim localM As Func(Of Integer, Integer) = C.m
Console.WriteLine(localM(5))
End Sub
I know I could use function(a) C.m(a)
but that is not pretty
and I don't want to create a new function every time
and is also sensitive to argument changes
as for why would I do that
I'm actually passing it to function as an argument
(someFunction(3, C::m))

You can do this:
Sub Main()
Dim localM As Func(Of Integer, Integer) = AddressOf C.m
Console.writeline(localM(5))
End Sub
You can see it work here:
https://dotnetfiddle.net/Uxl0Y7
I didn't change anything in the sample class, except to complete the function so it returns a value (required for the function to compile) and to fix your lousy capitalization.
I'm actually passing it to function as an argument
In that case:
Sub Main()
Dim localM As Func(Of Integer, Integer) = AddressOf C.m
Foo(localM)
' Or
Foo(AddressOf C.m)
End Sub
Sub Foo(theMethod As Func(Of Integer, Integer))
Console.WriteLine(theMethod(5))
End Sub
In either case, the trick is to do two things:
Define either an Action (for a Sub) or Func (for a Function) that matches the signature of the target method. In this case, it's Func(Of Integer, Integer). Any method up to 8 arguments can be mapped this way, but you do have to know the signature in advance.
Use AddressOf to capture the reference to the method.

Is this what you are looking for?
Class C
Public Shared Add1 As Func(Of Integer, Integer) = Function(value As Integer)
Return value + 1
End Function
End Class
to use
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim foo As Integer = C.Add1(3)
Debug.WriteLine(foo)
End Sub
edit
Class C
Public Shared Add1 As Func(Of Integer, Integer) = Function(value As Integer)
Return value + 1
End Function
Public Shared DebugStr As Action(Of String, String) = Sub(first As String, second As String)
Debug.WriteLine("One-{0} Two-{1}",
first, second)
End Sub
End Class
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim foo As Integer = C.Add1(7)
Debug.WriteLine(foo)
C.DebugStr("Quick", "Fox")
End Sub

Related

Getting Installed Steam Games From Registry

Can someone help me with this error I'm getting? Error14 'Using' operand of type 'System.Collections.Generic.List(Of String)' must implement 'System.IDisposable'
Public Function GetInstalledGames() As Object
Dim enumerator As IEnumerator(Of String) = Nothing
Dim list As List(Of String) = Directory.GetFiles(String.Concat(Me.SteamPath, "\steamapps")).ToList()
Using strs As List(Of String) = New List(Of String)()
enumerator = list.Distinct().GetEnumerator()
While enumerator.MoveNext()
Dim current As String = enumerator.Current
If (current.Contains("appmanifest_") And current.Contains(".acf")) Then
strs.Add(Path.GetFileName(current).Replace("appmanifest_", "").Replace(".acf", ""))
End If
End While
End Using
Return strs
End Function
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
Dim enumerator As IEnumerator(Of String) = Nothing
Me.tbOutput.Text = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
Me.SteamPath = Conversions.ToString(Me.GetSteamPath())
Using installedGames As List(Of String) = DirectCast(Me.GetInstalledGames(), List(Of String))
enumerator = installedGames.Distinct().GetEnumerator()
While enumerator.MoveNext()
Dim current As String = enumerator.Current
Me.lbGames.Items.Add(current)
End While
End Using
End Sub
Stop writing explicit enumerator loops for no reason
Make your functions return types that make sense instead of Object
Don’t sprinkle Using into code without knowing what it does
Pass data between functions through arguments, not class fields
Private Shared Function GetInstalledGames(steamPath As String) As IEnumerable(Of String)
Dim result As New List(Of String)
For Each name In Directory.GetFiles(Path.Combine(steamPath, "steamapps"))
If name.Contains("appmanifest_") AndAlso name.Contains(".acf") Then
result.Add(Path.GetFileNameWithoutExtension(name).Replace("appmanifest_", ""))
End If
Next
Return result
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs)
Me.tbOutput.Text = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
Dim steamPath As String = Me.GetSteamPath()
For Each current In GetInstalledGames(steamPath).Distinct()
Me.lbGames.Items.Add(current)
Next
End Sub

I want to get the generic dictionary as return value of function in vb.net

I want to get the generic dictionary as return value of function in vb.net.
How can I get this?
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim buttons As Dictionary(Of Integer, Button) = generateControls(Of Button)(3)
Dim textBoxes As Dictionary(Of Integer, TextBox) = generateControls(Of TextBox)(3)
End Sub
Private Function generateControls(Of T)(repeat As Integer) As Dictionary(Of Integer, T)
Dim dic As New Dictionary(Of Integer, T)
For i As Integer = 0 To repeat - 1
Dim control As New T
dic.Add(i, control)
Next
Return dic
End Function
You need to specify a type constraint declaring that the type has a default constructor.
Use generateControls(Of T As New) instead of generateControls(Of T)
However I prefer:
Dim result = Enumerable.Range(0, 3).
ToDictionary(Function(i) i, Function(i) New TextBox() With {... })

Having trouble with arguments and classes in VB

I am having trouble with getting classes to work and passing arguments for those classes. i have figured out most of the other Errors i had on my own, but there is one error that is really bugging me. the error i am getting is for "objAttendee". the error says "Argument not specified for parameter "strFirstName" of public Sub New(ByVal strFirstName As String, ByVal strLastName As String, ByVal strCourses As String, ByVal intDays As String)". i am not at all sure how to fix this problem.
can anyone help me out with this?
Option Strict On
Public Class Attendee
Dim objAttendee As New Attendee
'class variables
Private _strFirstName As String
Private _strLastName As String
Private _strCourses As String
Private _intDays As Integer
Private _decTotal As Decimal
Private _decCostPerDay As Decimal = 350D
Private _decPreConferenceCost As Decimal = 675D
Sub New(ByVal strFirstName As String, ByVal strLastName As String, ByVal strCourses As String, ByVal intDays As String)
'Contructor
_strFirstName = strFirstName
_strLastName = strLastName
_strCourses = strCourses
_intDays = Convert.ToInt32(intDays)
End Sub
Function ComputeCourseCosts() As Decimal
'Calculates the cost if a pre-conference course is not selected
_decTotal = _intDays * _decCostPerDay
Return _decTotal
End Function
Function ComputePreConferenceCosts() As Decimal
'Calculates the cost if a pre-conference course is selected
_decTotal = _intDays * _decCostPerDay + _decPreConferenceCost
Return _decTotal
End Function
End Class
"Argument not specified for parameter ".....
Plutonix told you the origin of the issue :
You're declaring a Attendee object within your Attendee Class (which doesn't really makes sense)
Public Class Attendee
Dim objAttendee As New Attendee ' <- offending code :P
But the constructor of that class is declared as follows :
Sub New(ByVal strFirstName As String, ByVal strLastName As String, ByVal strCourses As String, ByVal intDays As String)
And you don't have a constructor without any parameter like :
Public Sub New() ' No parameter required
' ...
End Sub
And you don't have to create/declare such variant of Attendee constructor, otherwise, you must have to define default values for _strFirstName, _strLastName, _strCourses and _intDays !
I think that... you were in the urge to test your Attendee class, and declared an Attendee variable inside it ;) .
No, you should declare Dim objAttendee As New Attendee(...) outside your class (in the main block of your program for example) with the appropriate parameters.
Private Sub ShowMyClass(sender As Object, e As EventArgs) Handles Button1.Click
Dim objAttendee As New Attendee("Simpson", "Homer", "Courses", "48")
MessageBox.Show(objAttendee.ComputeCourseCosts().ToString())
End Sub

Is it possible to make a shared function generic?

I can create classes that use generics, however I was wondering if it is possible to apply this to a shared method rather than rely on the caller casting to the correct type.
This is the method:
Public Shared Function DeserializeObject(ByVal serializedXml As String, ByVal givenType As System.Type) As Object
Dim serializer As New XmlSerializer(givenType)
Return serializer.Deserialize(New IO.StringReader(serializedXml))
End Function
I'm pretty sure this can't be done, but thought I'd check (if so Extra points will be awarded if someone can technically explain why the compiler can't do this).. Alternative suggestions would also be appreciated.
Public Shared Function StronglyTypedDeserializeObject(Of T)
(ByVal serializedXml As String) As T
Dim serializer As New XmlSerializer(GetType(T))
Return DirectCast(
serializer.Deserialize(New IO.StringReader(serializedXml))
, T)
End Function
Note that invocations will have to supply the type expected:
Dim foo As MyType
= Utility.StronglyTypedDeserializeObject(Of MyType)(sourceXml)
There's no reason you couldn't create a generic version of the function. e.g.:
Public Shared Function Deserialize(Of T)(ByVal serializedXml As String) As T
Dim serializer As New XmlSerializer(GetType(T))
Return DirectCast(serializer.Deserialize(New StringReader(serializedXml)), T)
End Function
The Following Example shows how you can do this. The esstential trick is remember that can you can use the GetType function a defined Generic for example GetType(MyObject(Of T))
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim Test1 As New MyObject(Of String)
Dim Test2 As New MyObject(Of Integer)
Dim Data As String = ""
Test1.Data = "Hello World"
Test2.Data = 1010101
Data = Test1.SerializeObject
Test1 = MyObject(Of String).DeserializeObject(Data)
Debug.Print(Test1.Data)
Data = Test2.SerializeObject
Test2 = MyObject(Of Integer).DeserializeObject(Data)
Debug.Print(Test2.Data)
End Sub
End Class
Public Class MyObject(Of T)
Public Data As T
Public Sub New()
End Sub
Public Shared Function DeserializeObject(ByVal serializedXml As String) As MyObject(Of T)
Dim serializer As New XmlSerializer(GetType(MyObject(Of T)))
Return serializer.Deserialize(New IO.StringReader(serializedXml))
End Function
Public Function SerializeObject() As String
Dim serializer As New XmlSerializer(GetType(MyObject(Of T)))
Dim Result As New IO.StringWriter()
serializer.Serialize(Result, Me)
Return Result.ToString
End Function
End Class
If you don't like fully qualifying the type to get at the shared member then you can do something like this.
Public Class MyObjectString
Inherits MyObject(Of String)
End Class
Then you can call MyObjectString.Deserialize

Confused with Events

I am very confused over a Raise Events example and using delegate as a function pointer:
I am clear with this function pointer example program below which creates a generic sort function for sorting integer arrays without changing the main sort function.
' Returns True if need to swap
Delegate Function CompareFunc(ByVal x As Integer, ByVal y As Integer) As Boolean
' Here are two alternative target methods for the delegate—one for an ascending sort and one for a
' descending sort:
Function SortAscending(ByVal x As Integer, ByVal y As Integer) As Boolean
If y < x Then
SortAscending = True
End If
End Function
Function SortDescending(ByVal x As Integer, ByVal y As Integer) As Boolean
If y > x Then
SortDescending = True
End If
End Function
' Now we can define the sort routine. Note the call to the Invoke method of the delegate:
Sub BubbleSort(ByVal CompareMethod As CompareFunc, ByVal IntArray( ) As Integer)
Dim i, j, temp As Integer
For i = 0 To Ubound(IntArray)
For j = i + 1 To Ubound(IntArray)
If CompareMethod.Invoke(IntArray(i), IntArray(j)) Then
Temp = IntArray(j)
IntArray(j) = IntArray(i)
IntArray(i) = Temp
End If
Next j
Next i
End Sub
' Here is some code to exercise this example:
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim i As Integer
Dim iArray() As Integer = New Integer( ) {6, 2, 4, 9}
' The code below tells us that we have created a generic sort function thus eliminating the need of having multiple sort function to do different sorts.
BubbleSort(AddressOf SortAscending, iArray)
For i = 0 To 3
Debug.WriteLine(CStr(iArray(i)))
Next
Debug.WriteLine
BubbleSort(AddressOf SortDescending, iArray)
For i = 0 To 3
Debug.WriteLine(CStr(iArray(i)))
Next
End Sub
Then this RaiseEvent example came along which confuses me, is it suppose to be an alternative to the example above?:
Module Module1
Dim WithEvents ValueInfo As New Value()
Class Value
Public Event ValueUp(ByVal Amount As Double)
Public Event ValueDown(ByVal Amount As Double)
Public Event Result(ByVal Amount As Double, ByVal AnnounceDate As DateTime)
Public Sub GenerateEvents()
RaiseEvent ValueUp(2)
RaiseEvent ValueDown(-5.5)
RaiseEvent Result(1.25, Now())
End Sub
End Class
Sub PriceGoingUp(ByVal Price As Double)
Console.WriteLine("Up: " & Price)
End Sub
Sub PriceGoingDown(ByVal Price As Double)
Console.WriteLine("Down: " & Price)
End Sub
Sub ResultAnnouncement(ByVal Amount As Double, ByVal AnnounceDate As DateTime)
Console.WriteLine("Result: " & Amount & " " & AnnounceDate)
End Sub
Sub Main()
AddHandler ValueInfo.ValueUp, AddressOf PriceGoingUp
AddHandler ValueInfo.ValueDown, AddressOf PriceGoingDown
AddHandler ValueInfo.Result, AddressOf ResultAnnouncement
ValueInfo.GenerateEvents()
End Sub
End Module
I would appreciate if someone can provide an explanation. Thanks!
The simplest way I know to describe the difference is like this.
A delegate is a reference to a single method or chain of methods that is callable using the same signature as the target method.
An event is an encapsulation of the mechanism for adding and removing method references to a delegate.
There is an important distinction to be made here. An event is not a delegate. It is the .NET way of implementing the observer pattern using delegates in a manner that prohibits event subscribers from mucking up the delegate chain.
RaiseEvent is VB's way of invoking the delegate through the event mechanism. Remember, delegates can reference more than one method so invoking a delegate could cause more than one method to execute.
You can read this article for a more detailed explanation.