Simple linear linked list in VB.NET using class - vb.net

How can a linear linked list be implemented in VB.NET using class?
How can this class be modified for linear linked list?
Also the methods for traversing the list, deleting nodes, etc.
Public Class clsHol
Private dt As Date
Private tp As String
Private remark As String
Public Function setValues(ByVal d As Date, ByVal t As String, ByVal r As String)
remark = r
tp = t
remark = r
End Function
Public Function getDate()
Return dt
End Function
Public Function getTyp()
Return tp
End Function
Public Function getRemark()
Return remark
End Function
End Class

Sample:
Sub Main()
Dim voLList As New LinkedList(Of clsHol)
voLList.AddFirst(new clsHol())
voLList.AddLast(new clsHol())
voLList.AddLast(new clsHol())
End Sub

Related

How to support contextual implicit conversions of custom object in Visual Basic .NET?

I want to use named error codes within my app. This should ensure, that every developer does not confuse numeric-only error codes with other codes, and also reduces the time a developer needs to realize what the error code should represent.
Compare this example:
Function New() As Integer
Return 0
End Function
with this example:
Function New() As Integer
Return ErrorCodes.ERROR_SUCCESS
End Function
Of course, I could let the developers write like the following:
Function New() As Integer
Return 0 ' ERROR_SUCCESS
End Function
However, the code above raises a pitfall when a developer updates the actual return code but forgets about the comment. Some developer look at the actual return code and some at the comment. I want to mitigate that confusion.
I come up the following class (extract):
Public Class ErrorCodes
Private msName As String = Nothing
Private miValue As Integer = 0
Public Shared ReadOnly ERROR_SUCCESS As ErrorCodes = New ErrorCodes("ERROR_SUCCESS", 0)
Private Sub New(ByVal psName As String, ByVal piValue As Integer)
msName = psName
miValue = piValue
End Sub
Public ReadOnly Property [Name] As String
Get
Return msName
End Get
End Property
Public ReadOnly Property [Value] As Integer
Get
Return miValue
End Get
End Property
Public Overrides Function ToString() As String
Return String.Format("[{0}]{1}", msName, miValue)
End Function
End Class
Now I want to use this ErrorCodes class like in the following example:
Function New() As Integer
Return ErrorCodes.ERROR_SUCCESS
End Function
As expected, I will produce an exception (type conversion) since the actual value I return is a instance of the class ErrorCodes instead of the generic data type Integer.
As you can see with the ToString() function, I let the class automatically/implicitly converts the instanced object into the generic data type String, when the class instance is assigned to a String typed variable.
Is there a way to do the same with the generic data type Integer like I did with ToString()?
I am using the .NET Framework 4.0, as for compatibility reasons with Windows XP SP3.
Another way to say what I want:
Dim stringVariable As String = ErrorCodes.ERROR_SUCCESS ' should be "[0]ERROR_SUCCESS".
Dim integerVariable As Integer = ErrorCodes.ERROR_SUCCESS ' should be 0.
I do not want to trigger implicit conversion warnings/errors, or to force the developer to typecast explicitly.
Yes you can do that with the use of Conversion Operators.
Here is the code:
Public Class Form1
Public Class ErrorCodes
Private msName As String = Nothing
Private miValue As Integer = 0
Public Shared Widening Operator CType(ByVal ec As ErrorCodes) As String
Return ec.ToString
End Operator
Public Shared Narrowing Operator CType(ByVal ec As ErrorCodes) As Integer
Return ec.Value
End Operator
Public Shared ReadOnly ERROR_SUCCESS As ErrorCodes = New ErrorCodes("ERROR_SUCCESS", 0)
Public Shared ReadOnly ERROR_FAILED As ErrorCodes = New ErrorCodes("ERROR_FAILED", 1)
Private Sub New(ByVal psName As String, ByVal piValue As Integer)
msName = psName
miValue = piValue
End Sub
Public ReadOnly Property [Name] As String
Get
Return msName
End Get
End Property
Public ReadOnly Property [Value] As Integer
Get
Return miValue
End Get
End Property
Public Overrides Function ToString() As String
Return String.Format("[{0}]{1}", msName, miValue)
End Function
End Class
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim em As String = ErrorCodes.ERROR_SUCCESS
Dim ev As Integer = ErrorCodes.ERROR_SUCCESS
Dim mm As String = String.Format("String: {0}, Value: {1}", em, ev)
MsgBox(mm)
End Sub
End Class
More info here
Hope this helps.
This, as jmcilhinney pointed out, uses Enums and the Description attribute.
Here is the class
'requires
' Imports System.Reflection
' Imports System.ComponentModel
Public Class ErrorCodes
Public Enum ErrCode 'these are the error codes
'note that the codes should be unique
<Description("Success")> ERROR_SUCCESS = 0
<Description("Error A")> ERROR_A = 1
End Enum
Public Class InfoForErrCode
Public TheDescription As String
Public TheValue As Integer
Public AsString As String
End Class
Public Shared Function Info(TheError As ErrCode) As InfoForErrCode
Dim rv As New InfoForErrCode
rv.TheDescription = GetDescription(TheError)
rv.TheValue = TheError
rv.AsString = TheError.ToString
Return rv
End Function
Private Shared Function GetDescription(TheError As ErrCode) As String
Dim rv As String = ""
Dim fi As FieldInfo = TheError.GetType().GetField(TheError.ToString())
Dim attr() As DescriptionAttribute
attr = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute),
False), DescriptionAttribute())
If attr.Length > 0 Then
rv = attr(0).Description
Else
rv = TheError.ToString()
End If
Return rv
End Function
End Class
And here is how it can be used
Dim foo As ErrorCodes.ErrCode = ErrorCodes.ErrCode.ERROR_SUCCESS
Dim inf As ErrorCodes.InfoForErrCode = ErrorCodes.Info(foo)
Stop 'examine inf
foo = ErrorCodes.ErrCode.ERROR_A
inf = ErrorCodes.Info(foo)
Stop 'examine inf

Pass a lambda to a generic function

I would like to create a generic class that can be used to contain items from a database table
As follows
Public Class RowCache(Of t)
Private items As New List(Of t)
Public Sub AddItem(item As t)
Me.items.Add(item)
End Sub
Public Function find(Filter As ?????) As t
????
End Function
End Class
Public Class useit
Public Sub test()
Dim ob As New RowCache(Of teamrow)
ob.find(func(rec) rec.teamcode)
Dim ob2 As New RowCache(Of employeerow)
ob2.find(func(rec) rec.employeeno)
End Sub
End Class
Is it possible to create the find method and if so how is it done
What goes in the parameter list
How do I use this in the find function
You could pass a lambda to the find function, which returns true if the item is found. You can combine this with Linq's SingleOrDefault to find the single item which is filtered.
Public Function find(filter As Func(Of t, Boolean)) As t
Return Me.items.SingleOrDefault(filter)
End Function
Then you can use it like this:
Dim result = ob.find(Function(rec) rec.teamcode = 1)

A class can only be a template for a single object not a template for a collection

I have a simple class List.vb which is the following:
Public Class List
Public fList As List(Of Integer)
Public Sub New()
fList = New List(Of Integer)
fList.Add(1)
fList.Add(2)
fList.Add(3)
fList.Add(4)
fList.Add(5)
End Sub
End Class
The Console application is using this class like the following:
Module Module1
Sub Main()
Dim fObject As List = New List
Dim cnt As Integer = 0
For Each x As Integer In fObject.fList
Console.WriteLine("hello; {0}", fObject.fList.Item(cnt).ToString())
cnt = cnt + 1
Next
Console.WriteLine("press [enter] to exit")
Console.Read()
End Sub
End Module
Can I change the class code so that List.vb is a list(of integer) type?
This would mean that in the Console code I could replace In fObject.fList with just In fObject?
Or am I barking up the wrong tree - should classes be single objects and lists should be collections of classes ?
Yes, you can do that. In order for an object to be compatible with For Each, it must have a GetEnumerator function:
Public Function GetEnumerator() As IEnumerator _
Implements IEnumerable.GetEnumerator
Return New IntListEnum(fList)
End Function
The IntListEnum class must, in turn, implement IEnumerator, like this:
Public Class IntListEnum Implements IEnumerator
Private listInt As List(Of Integer)
Dim position As Integer = -1
Public Sub New(ByVal fList As List(Of Integer))
listInt = fList
End Sub
Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
position = position + 1
Return (position < listInt.Count)
End Function
Public Sub Reset() Implements IEnumerator.Reset
position = -1
End Sub
Public ReadOnly Property Current() As Object Implements IEnumerator.Current
Get
Try
Return listInt(position)
Catch ex As IndexOutOfRangeException
Throw New InvalidOperationException()
End Try
End Get
End Property
End Class
Now you can make fList private, and iterate your List as follows:
For Each x As Integer In fObject
You can see a complete example here.
The answer that dasblinkenlight has provided is excellent, but if all you need is a list that of integers that is pre-populated, you can just inherit from List(Of Integer) and then have the class populate itself in the constructor:
Public Class List
Inherits List(Of Integer)
Public Sub New()
Add(1)
Add(2)
Add(3)
Add(4)
Add(5)
End Sub
End Class
When you inherit from List(Of Integer), your class automatically gets all of the functionality implemented by that type, so your class also becomes a list class that works the same way. Then, you can just use it like this:
Dim fObject As New List()
For Each x As Integer In fObject
Console.WriteLine("hello; {0}", x)
Next

Do local variables in shared method work like static variable in C?

Will the list in this shared method keep its state throughout the life of the method? Or will a new list be created every time this method is called?
Protected Shared Function newResxNodes(ByVal newName As String, ByVal newValue As String, Optional ByVal newComment As String = "") As List(Of ResXDataNode)
Dim newResxNodesList As List(Of ResXDataNode) = New List(Of ResXDataNode)
Dim newResxNode As ResXDataNode = New ResXDataNode(newName, newValue)
If newComment <> String.Empty Then
newResxNode.Comment = newComment
End If
newResxNodesList.Add(newResxNode)
Return newResxNodesList
End Function
No, It does not work like static variables in C. It will be a new list for every call. If you want to retain the list and list items, create a shared class field.
I've done a test and it returns 3 lines.
Module Module1
Class b
Public Sub New()
Console.WriteLine("New")
End Sub
End Class
Class a
Public Shared Sub Test()
Dim c As b = New b
End Sub
End Class
Sub Main()
a.Test()
a.Test()
a.Test()
Console.ReadLine()
End Sub
End Module

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