Having trouble with arguments and classes in VB - vb.net

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

Related

referencing VisualBasic methods

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

When ever I change an attribute of a class, the window won't open

When ever I try to change an attribute in the load method of a class I created, it won't let me open it. If I leave the load method blank or put anything else there, it works fine.
Public Class Main
'SHIPS
Dim AirCraftCarrier As Ship
Private Sub Main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
AirCraftCarrier.name = "ACC" ' These won't work
AirCraftCarrier.SetAttributes("ACC", AirCraftCarrier_image, 5, "vertical", new_pos, False, False) ' If I leave it blank or keep anything else here, it opens fine.
End Sub
End Class
Public Class Ship
Public name As String
Public image As PictureBox
Public direction As String
Public selection As Boolean
Public placed As Boolean
Public location(2) As Integer
Public Sub SetAttributes(ByVal name1 As String, ByVal image1 As PictureBox, ByVal length1 As Integer, ByVal direction1 As String, ByVal location1 As Array, ByVal selected1 As Boolean, ByVal placed1 As Boolean)
name = name1
image = image1
direction = direction1
selection = selected1
placed = placed1
location(0) = location1(0)
location(1) = location1(1)
End Sub
End Class
First changes to Ship. Classes tend to use Properties rather than fields:
Public Class Ship
Public Property name As String
Public Property image As PictureBox ' bad name; Net has an Image class
' etc
' set essential props via the constructor:
Public Sub New(sName As String, picB As PictureBox)
name = sName
image = picB
End Sub
Then in main for creating it:
Public Class Main
Dim AirCraftCarrier As Ship ' this is just a variable declaration
Private Sub Main_Load(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles MyBase.Load
' Create an instance:
AirCraftCarrier = New Ship("ACC", frm.PicBoxName)
' set other properties
AirCraftCarrier.Direction = "SSW"
AirCraftCarrier.Foo = "Bar"
End Sub
End Class
With a constructor you can pass the essential information, like the unique name to the class when you create it. This is used instead of the SetAttributes sub.

Retrieve a object from a list of objects in visual basic and use it to fill text/combo boxes

I have a class as seen below:
Public Class parameters
Public Property test As String
Public Property test_type As String
Public Property user_test_name As String
Public Property meas As String
Public Property spec As String
...etc
End Class
I make a list of objects that I import from a csv somewhere. The user_test_name's from the list gets sent to a list box:
For Each parameters In param
' MsgBox(parameters.user_test_name)
ListBox1.Items.Add(parameters.user_test_name)
Next
now when the user selects something from the list i want the rest of the properties of that particular user_test_name object to populate in certain text/combo boxes in the application. Here is how I grab what is selected.
Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
Dim selected_name As String = ListBox1.SelectedItem()
' MsgBox(selected_name)
find_object_by_user_test_name(selected_name)
End Sub
Now i'm having difficulty finding the object with the selected_name from the list and using its properties to fill the text.combo boxes. I tried the following to no success:
Public Sub find_object_by_user_test_name(ByVal description)
MsgBox(description)
Dim matches = From parameters In param
Where parameters.user_test_name = description
Select parameters
' MsgBox(matches)
' MsgBox(matches.user_test_name)
TextBox1.Text = matches.test
TextBox2.Text = matches.test_name
etc,,, on and on
' populate_area(matches)
End Sub
Instead of adding the name (a string) to the ListBox, add your actual INSTANCE to it.
First, override ToString() in your class so that it displays properly in your ListBox:
Public Class parameters
Public Property test As String
Public Property test_type As String
Public Property user_test_name As String
Public Property meas As String
Public Property spec As String
Public Overrides Function ToString() As String
Return user_test_name
End Function
End Class
Next, add each instance to the ListBox:
For Each parameters In param
ListBox1.Items.Add(parameters)
Next
Now, the SelectedIndexChanged() event, you can cast the SelectedItem() item back to parameters and you already have everything at your disposal:
Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
If ListBox1.SelectedIndex <> -1 Then
Dim P As parameters = DirectCast(ListBox1.SelectedItem, parameters)
' ... do something with "P" ...
Debug.Print(P.user_test_name & " --> " & P.test)
End If
End Sub
If the user_test_names are unique, it may be easier to use a dictionary and retrieve the objects that way.
Dim params As New Dictionary(Of String, parameters)
params.add(MyParameterObject.user_test_name, MyParameterObject)
Then
Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
Dim selected_name As String = ListBox1.SelectedItem()
Dim selected_param as parameters = params(selected_name)
End Sub
Something like this should do it:
Public Sub find_object_by_user_test_name(ByVal description As String)
' assuming param is your list of parameter objects
For Each p In param
If p.user_test_name = description Then
TextBox1.Text = p.test
TestBox2.Text = p.test_name
...
Exit For
End If
Next
End Sub
A few notes about your code. First, you can't allow two objects to have the same user_test_name. Second, you can't use parameters as a variable name if you already have a class called parameters in your current namespace (which you do).
There is a simpler solution than any of these--just do the following:
Dim i as Integer = ListBox1.SelectedIndex
Then you can use i as an index to your original list of objects.

Passing structure as argument through files/functions

I can't get to pass structure as argument through subs/functions in different files of single vbnet project like I use to in earlier MS basic versions.
Here is short example of situation:
Module1.vb
Imports System.IO
Structure mymultitry
Dim index As Integer
<VBFixedString(6)> Dim name As String
Dim weight As Double
End Structure
Module Module1
Public mysetupfile = "mysetup.dat"
Public Sub rwfile(ByVal rw As Integer, ByVal myrecord As Integer, ByVal mmt As mymultitry)
'EDIT: Thanks to SteveDog - proper line should be:
'Public Sub rwfile(ByVal rw As Integer, ByVal myrecord As Integer, ByRef mmt As mymultitry)
Dim fnum As Integer
fnum = FreeFile()
FileOpen(fnum, mysetupfile, OpenMode.Random, OpenAccess.ReadWrite, OpenShare.Shared, Len(mmt))
If rw Then
FilePut(fnum, mmt, myrecord)
Else
FileGet(fnum, mmt, myrecord)
End If
FileClose(fnum)
End Sub
End Module
Form1.vb
Public Class Form1
Dim mmt As mymultitry
Dim mmt1 As mymultitry
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
With mmt
.index = 4
.name = "Helga"
.weight = 128.1445
End With
rwfile(1, 1, mmt) 'write
rwfile(0, 1, mmt1) 'read
'all zero here !?!
Debug.Print(mmt1.index)
Debug.Print(mmt1.name)
Debug.Print(mmt1.weight)
End Sub
End Class
File "mysetup.dat" is reachable and data is saved correctly what I can see with HxD.
But read part seem's to not work as expected.
Please any help on reliable passing structure as argument without too much public elements based on upper example.
I strongly suggest you rewrite your code to use the new .NET IO methods in the System.IO.File class, but, that aside, I think your problem with your existing code is that you need to change your mmt argument from ByVal to ByRef.

vb.net - add object to arraylist

I'm having some trouble adding an object to an arraylist.
Basically the object has two properties (file id/name), but I can't figure out how to assign those properties. During runtime it errors out with public member on the object not found.
Private QueueList As New ArrayList
Public Sub Queue(ByVal FileName As String, ByVal FileID As Integer)
Dim QueueObj As New Object
QueueObj.FileID = "Test 1"
QueueObj.FileName = "Test 2"
QueueList.Add(QueueObj)
End Sub
I'd also like to know how I can do a loop on the arraylist and access the two properites on each record.
Thanks!
You can't just use "Object" for this. You need to build your own class:
Public Class File
Public Property FileID As Integer
Public Property FileName As String
Public Sub New ()
End Sub
Public Sub New(ByVal FileName As String, ByVal FileID As Integer)
Me.FileID = FileID
Me.FileName = FileName
End Sub
End Class
And then build your Queue like this:
Private QueueList As New ArrayList()
Public Sub Queue(ByVal FileName As String, ByVal FileID As Integer)
QueueList.Add(New File(FileName, FileID))
End Sub
Public Sub Queue(ByVal FileObj As File)
QueueList.Add(FileObj)
End Sub
Or, even better, use generics:
Public QueueList As New List(Of File)()
Public Sub Queue(ByVal FileName As String, ByVal FileID As Integer)
QueueList.Add(New File(FileName, FileID))
End Sub
Public Sub Queue(ByVal FileObj As File)
QueueList.Add(FileObj)
End Sub
Then, to loop over list:
For Each item As File In QueueList
'Console.WriteLine(item.FileID & vbTab & item.FileName)
Next item
You need to switch to an object to hold your file information, and drop ArrayList for a strongly typed collection.
public class QueueFile
public Property FileID as integer
public property FileName as string
end class
...
Private QueueList As New List(Of QueueFile)
Public Sub Queue(ByVal FileName As String, ByVal FileID As Integer)
Dim QueueObj As New QueueFile
QueueObj.FileID = "Test 1"
QueueObj.FileName = "Test 2"
QueueList.Add(QueueObj)
End Sub
If you only have two values, you may find using a generic Dictionary even better than an ArrayList (requiring boxing and unboxing the types) or List(Of T) which retains type safety.
Private QueueList As New Dictionary(of Integer, String)
Public Sub Queue(ByVal FileName As String, ByVal FileID As Integer)
QueueList.Add(FileID, FileName)
End Sub
If you really want a Queue as your method name indicates, consider using the generic Queue. Also, if you only need a key/value pair, you don't need to create your own class. You can use the generic KeyValuePair(Of T, S):
Private QueueItems As New Queue(Of KeyValuePair(Of Integer, String))
Public Sub Queue(ByVal FileName As String, ByVal FileID As Integer)
QueueItems.Enqueue(New KeyValuePair(Of Integer, String)(FileID, FileName))
End Sub
To get items out, use the QueueItems.Dequeue.