Home All Groups Group Topic Archive Search About

beginner question about classes

Author
21 Jan 2006 1:37 AM
me
Hi All,

I am new to Classes and learniing the ropes with VB.NET express

Here's my question - say I have a want to manage a list of books.
Each book has an Author, Title and ISBN

Now, I am used to using Arrays so I would normally do something like this:

Set an array up during the init routine (called from form_load) say of
Books(100) of type Book (which is setup with Author as string, Title as
string etc.)

Allow the user to add/delete/edit a new book (with a simple VB form)

When it comes to saving the file, just cycle through the array and dump each
line to a CSV text file.

Opening - again cycle through the CSV file and fill the array.

Now - here's my question:

How can I do this using classes? I have set up a class (called Book) with
properties such as Title, Author, ISBN and can get/set them

I create a new instance, i.e. myBook = New Book.Book

However, I now dont understand.... This creates one instance, which i can
fill with information. However, if i want another book, I have to create

myBook2 = New Book.Book

So how does one then cycle through these items when saving? How do we create
all the instances when first loading the CSV file?

I tried myBook(1000) = New Book.Book but got an error.

I tried using

myBookGroup as Collections

but still... I dont understand - how can I refer to each individual book in
a loop for example when reading/writing the file?

Am I misunderstanding the point? Should I just stick with arrays?

Thanks






now I can create a collection

Author
21 Jan 2006 3:02 AM
Armin Zingler
Show quote Hide quote
"me" <c**@notvalid.com> schrieb
> Hi All,
>
> I am new to Classes and learniing the ropes with VB.NET express
>
> Here's my question - say I have a want to manage a list of books.
> Each book has an Author, Title and ISBN
>
> Now, I am used to using Arrays so I would normally do something like
> this:
>
> Set an array up during the init routine (called from form_load) say
> of Books(100) of type Book (which is setup with Author as string,
> Title as string etc.)
>
> Allow the user to add/delete/edit a new book (with a simple VB form)
>
> When it comes to saving the file, just cycle through the array and
> dump each line to a CSV text file.
>
> Opening - again cycle through the CSV file and fill the array.
>
> Now - here's my question:
>
> How can I do this using classes? I have set up a class (called Book)
> with properties such as Title, Author, ISBN and can get/set them
>
> I create a new instance, i.e. myBook = New Book.Book
>
> However, I now dont understand.... This creates one instance, which
> i can fill with information. However, if i want another book, I have
> to create
>
> myBook2 = New Book.Book


If your array's name is 'Books', you can store the reference to a new book
directly in this array:

    Books(Index) = New Book.Book

Now the item at position Index points to the book that has been created in
the same line.

'Index' is a variable that you will have to manage. It should point to the
first empty position within the array. At the beginning, the value of Index
is 0. After you stored a reference to a new book at the position that Index
points to, Index has to be incremented by 1, so next time you will store a
new book at the next position in the array. There are alternatives better
than arrays that I'll mention below.

After this, you can set the book's properties:

    Books(Index).Title = ...
    Books(index).author = ...

Or, if you have many properties:

    With Books(Index)
        .Title = ...
        .author = ...
    End With


Show quoteHide quote
> So how does one then cycle through these items when saving? How do
> we create all the instances when first loading the CSV file?
>
> I tried myBook(1000) = New Book.Book but got an error.
>
> I tried using
>
> myBookGroup as Collections
>
> but still... I dont understand - how can I refer to each individual
> book in a loop for example when reading/writing the file?
>
> Am I misunderstanding the point? Should I just stick with arrays?


Using arrays and classes is not a contradiction. BTW, an array is class,
too.

To loop through all books in the array:

    For i as integer = 0 to index - 1
        Debug.writeline(books(i).title)
        Debug.writeline(books(i).author)
    next i

You see how to access the books in the array and how to access the
properties. You can access them the same way if you write them to a file. I
don't know how you do it, thus I use debug.writline here.

There are alternatives:

    For i as integer = 0 to index - 1
        dim LoopBook as book
        LoopBook = books(i)
        Debug.writeline(LoopBook.title)
        Debug.writeline(LoopBook.author)
    next i

or

    For i as integer = 0 to index - 1
        with books(i)
            Debug.writeline(.title)
            Debug.writeline(.author)
        end with
    next i


Now we come to how to read the books from the file. I don't know how exactly
you intend to read the file, thus I focus on creating the objects and
storing them in the array:


    index = 0

    do until end-of-file
        dim Author, Title as string
        'read one line and store the values in 'Author' and 'Title'
        '...

        books(index) = new book
        books(index).title = title
        books(index).author = author
        index += 1
    loop


As you see, using an array can be much work:

- You can not change the size of an array. If you need more/less items, you
have to create a new array and copy the content of the old array into the
new one (ReDim Preserve).

- If you define your array being able to hold 100 items maximum, you need an
additional variable, called 'Index' in this example, that tracks the number
of items that are used within the array.

- You can not delete items from the array. You would have to copy items to
avoid having an unused item in the array. An unused item is 'Nothing', i.e.
it does not point to a book.

- If, within the array, unused items are allowed, you would have to loop
through all the items if you want to find an unused item where you can store
the reference to a new book.


Therefore, you'd better use another sort of collection. An arraylist is
often used. See the namespace System.Collections for more information. With
an arraylist, you can add and remove items without caring about the space
for new/removed items.

    dim books as new arraylist

To add a new book - also when reading the file:

    dim b as book

    b = new book
    b.title = ...
    b.author = ...

    books.add(b)    'add the book to the arraylist

Use books.RemoveAt (or books.remove) to remove a book from the arraylist.
Use the arraylist's count property to get the number of items in the list.
As an arraylist can contain references to any type of object, the type of
the arraylist's 'Item' property is 'Object'. For this reason, you have to
use type casting:

    dim b as book

    b = directcast(books(17), book)
    debug.writline(b.title)
    debug.writline(b.author)



See also:
http://msdn.microsoft.com/library/en-us/vbcn7/html/vaconManagingGroupsOfObjects.asp

http://msdn.microsoft.com/library/en-us/cpguide/html/cpcongroupingdataincollections.asp

http://msdn.microsoft.com/library/en-us/vbcon/html/vbconComponentsThatContainOtherComponents.asp
(especially: "Walkthrough: Creating Your Own Collection Class")


(As I see now, the links contain already all you need. :-)


Armin
Author
22 Jan 2006 9:50 PM
me
Show quote Hide quote
"Armin Zingler" <az.nospam@freenet.de> wrote in message
news:eJ5dKljHGHA.1332@TK2MSFTNGP10.phx.gbl...
> "me" <c**@notvalid.com> schrieb
>> Hi All,
>>
>> I am new to Classes and learniing the ropes with VB.NET express
>>
>> Here's my question - say I have a want to manage a list of books.
>> Each book has an Author, Title and ISBN
>>
>> Now, I am used to using Arrays so I would normally do something like
>> this:
>>
>> Set an array up during the init routine (called from form_load) say
>> of Books(100) of type Book (which is setup with Author as string,
>> Title as string etc.)
>>
>> Allow the user to add/delete/edit a new book (with a simple VB form)
>>
>> When it comes to saving the file, just cycle through the array and
>> dump each line to a CSV text file.
>>
>> Opening - again cycle through the CSV file and fill the array.
>>
>> Now - here's my question:
>>
>> How can I do this using classes? I have set up a class (called Book)
>> with properties such as Title, Author, ISBN and can get/set them
>>
>> I create a new instance, i.e. myBook = New Book.Book
>>
>> However, I now dont understand.... This creates one instance, which
>> i can fill with information. However, if i want another book, I have
>> to create
>>
>> myBook2 = New Book.Book
>
>
> If your array's name is 'Books', you can store the reference to a new book
> directly in this array:
>
>    Books(Index) = New Book.Book
>
> Now the item at position Index points to the book that has been created in
> the same line.
>
> 'Index' is a variable that you will have to manage. It should point to the
> first empty position within the array. At the beginning, the value of
> Index
> is 0. After you stored a reference to a new book at the position that
> Index
> points to, Index has to be incremented by 1, so next time you will store a
> new book at the next position in the array. There are alternatives better
> than arrays that I'll mention below.
>
> After this, you can set the book's properties:
>
>    Books(Index).Title = ...
>    Books(index).author = ...
>
> Or, if you have many properties:
>
>    With Books(Index)
>        .Title = ...
>        .author = ...
>    End With
>
>
>> So how does one then cycle through these items when saving? How do
>> we create all the instances when first loading the CSV file?
>>
>> I tried myBook(1000) = New Book.Book but got an error.
>>
>> I tried using
>>
>> myBookGroup as Collections
>>
>> but still... I dont understand - how can I refer to each individual
>> book in a loop for example when reading/writing the file?
>>
>> Am I misunderstanding the point? Should I just stick with arrays?
>
>
> Using arrays and classes is not a contradiction. BTW, an array is class,
> too.
>
> To loop through all books in the array:
>
>    For i as integer = 0 to index - 1
>        Debug.writeline(books(i).title)
>        Debug.writeline(books(i).author)
>    next i
>
> You see how to access the books in the array and how to access the
> properties. You can access them the same way if you write them to a file.
> I
> don't know how you do it, thus I use debug.writline here.
>
> There are alternatives:
>
>    For i as integer = 0 to index - 1
>        dim LoopBook as book
>        LoopBook = books(i)
>        Debug.writeline(LoopBook.title)
>        Debug.writeline(LoopBook.author)
>    next i
>
> or
>
>    For i as integer = 0 to index - 1
>        with books(i)
>            Debug.writeline(.title)
>            Debug.writeline(.author)
>        end with
>    next i
>
>
> Now we come to how to read the books from the file. I don't know how
> exactly
> you intend to read the file, thus I focus on creating the objects and
> storing them in the array:
>
>
>    index = 0
>
>    do until end-of-file
>        dim Author, Title as string
>        'read one line and store the values in 'Author' and 'Title'
>        '...
>
>        books(index) = new book
>        books(index).title = title
>        books(index).author = author
>        index += 1
>    loop
>
>
> As you see, using an array can be much work:
>
> - You can not change the size of an array. If you need more/less items,
> you
> have to create a new array and copy the content of the old array into the
> new one (ReDim Preserve).
>
> - If you define your array being able to hold 100 items maximum, you need
> an
> additional variable, called 'Index' in this example, that tracks the
> number
> of items that are used within the array.
>
> - You can not delete items from the array. You would have to copy items to
> avoid having an unused item in the array. An unused item is 'Nothing',
> i.e.
> it does not point to a book.
>
> - If, within the array, unused items are allowed, you would have to loop
> through all the items if you want to find an unused item where you can
> store
> the reference to a new book.
>
>
> Therefore, you'd better use another sort of collection. An arraylist is
> often used. See the namespace System.Collections for more information.
> With
> an arraylist, you can add and remove items without caring about the space
> for new/removed items.
>
>    dim books as new arraylist
>
> To add a new book - also when reading the file:
>
>    dim b as book
>
>    b = new book
>    b.title = ...
>    b.author = ...
>
>    books.add(b)    'add the book to the arraylist
>
> Use books.RemoveAt (or books.remove) to remove a book from the arraylist.
> Use the arraylist's count property to get the number of items in the list.
> As an arraylist can contain references to any type of object, the type of
> the arraylist's 'Item' property is 'Object'. For this reason, you have to
> use type casting:
>
>    dim b as book
>
>    b = directcast(books(17), book)
>    debug.writline(b.title)
>    debug.writline(b.author)
>
>
>
> See also:
> http://msdn.microsoft.com/library/en-us/vbcn7/html/vaconManagingGroupsOfObjects.asp
>
> http://msdn.microsoft.com/library/en-us/cpguide/html/cpcongroupingdataincollections.asp
>
> http://msdn.microsoft.com/library/en-us/vbcon/html/vbconComponentsThatContainOtherComponents.asp
> (especially: "Walkthrough: Creating Your Own Collection Class")
>
>
> (As I see now, the links contain already all you need. :-)
>
>
> Armin


Thanks for the feedback Armin,

So is an arraylist like a collection? Only, not for classes, just for
variables with types?
Author
22 Jan 2006 10:13 PM
Armin Zingler
"me" <c**@notvalid.com> schrieb
>
>
> Thanks for the feedback Armin,
>
> So is an arraylist like a collection?

I think the links provided explain each type of collection in detail. :-) I
can not explain the differences better.

> Only, not for classes, just for variables with types?

I do not know what you mean with "variables with types". Every variable has
a type. You can store every object in an Arraylist.

A "collection" is both, a general term for Array, Arraylist, Hashtable and
all other classes in the System.Collections namespace, as well as the name
of a class in the Microsoft.VisualBasic namespace. It depends on your needs
what type of collection you should use.


Armin
Author
21 Jan 2006 3:48 AM
_AnonCoward
Show quote Hide quote
"me" <c**@notvalid.com> wrote in message
news:43d1906b$0$23295$db0fefd9@news.zen.co.uk...
:
: Hi All,
:
: I am new to Classes and learniing the ropes with VB.NET express
:
: Here's my question - say I have a want to manage a list of books.
: Each book has an Author, Title and ISBN
:
: Now, I am used to using Arrays so I would normally do something like this:
:
: Set an array up during the init routine (called from form_load) say of
: Books(100) of type Book (which is setup with Author as string, Title as
: string etc.)
:
: Allow the user to add/delete/edit a new book (with a simple VB form)
:
: When it comes to saving the file, just cycle through the array and dump
: each line to a CSV text file.
:
: Opening - again cycle through the CSV file and fill the array.
:
: Now - here's my question:
:
: How can I do this using classes? I have set up a class (called Book) with
: properties such as Title, Author, ISBN and can get/set them
:
: I create a new instance, i.e. myBook = New Book.Book
:
: However, I now dont understand.... This creates one instance, which i can
: fill with information. However, if i want another book, I have to create
:
: myBook2 = New Book.Book
:
: So how does one then cycle through these items when saving? How do we
: create all the instances when first loading the CSV file?
:
: I tried myBook(1000) = New Book.Book but got an error.
:
: I tried using
:
: myBookGroup as Collections
:
: but still... I dont understand - how can I refer to each individual book
: in a loop for example when reading/writing the file?
:
: Am I misunderstanding the point? Should I just stick with arrays?
:
: Thanks


Here is one approach. Note that I'm ultimately defining an array of Book
objects and I'm using the ArrayList method for generating that array. This
isn't the approach I'd use in a real project - rather, I'd use a class that
inherits from CollectionBase. However, I don't have time to develop that for
you which is why I put together this example. I recommend you read up on the
CollectionBase class as well as Generics if you're using version 2.0 of the
framework (VB 2005).


'-------------------------------------------
'here are the namespaces we'll be using
'-------------------------------------------
Imports System
Imports System.Collections
Imports System.Io


'-------------------------------------------
'Define a function that reads a file and returns an array
'of book objects
'-------------------------------------------
Private Function GetBooks(FilePath As String) As Book()

  'this is the object we'll ultimately return
  Dim Books() As Book

  'we're going to use an array list to store the initial collection
  'of book items
  Dim AL As New ArrayList

  'and we'll need a stream reader in order to read the file
  Dim sr As StreamReader
  Dim Entry As String


  'first, let's open the file
  sr = New StreamReader(File.OpenRead(FilePath))


  'next, read in each line of data from the file and create
  'a book object for it
  Do
    Entry = sr.ReadLine

    'convert this line of data into a book object
    If Not Entry Is Nothing Then

      'since this is a column delimited line, split it apart
      Dim arr() As String = Split(Entry, ",")

      'define a new book object and populate its values
      Dim B As New Book
      B.Title = arr(0)
      B.Author = arr(1)
      B.ISBN = arr(2)

      'now, add it to the array list
      AL.Add(B)
    End If


  'keep going until we reach the end of the file
  Loop Until Entry = Nothing


  'create an array of book objects of the correct size
  'and populate it from the array list
  Redim Books(AL.Count - 1)
  For ndx As Integer = 0 To AL.Count - 1

    'since the array list only stores Object types, we'll need to
    'cast the object as a book type
    Books(ndx) = CType(AL.Item(ndx), Book)
  Next

  'and return the array
  Return Books
End Function



'-------------------------------------------
'Here's a quick test of this function
'-------------------------------------------
Public Sub Main

  'here is the target array we'll be using
  Dim mBooks() As Book

  'read in the contents of "books.csv" found in the same directory
  'as this application
  mBooks = GetBooks("books.csv")

  'print out the results of this operation
  For Ndx As Integer = 0 To UBound(mBooks)
    Dim B As Book = mBooks(ndx)
    Console.WriteLine(B.Title & ": " & B.Author & " : " & B.ISBN)
  Next

End Sub



HTH


Ralf
--
--
----------------------------------------------------------
*             ^~^                   ^~^                  *
*          _ {~ ~}                 {~ ~} _               *
*         /_``>*<                   >*<''_\              *
*        (\--_)++)                 (++(_--/)             *
----------------------------------------------------------
There are no advanced students in Aikido - there are only
competent beginners. There are no advanced techniques -
only the correct application of basic principles.
Author
21 Jan 2006 8:12 AM
Cor Ligthert [MVP]
Me,

If you use a dataset\table to read\write as XML instead of CSV than your
problem becomes very simple. (while you have than as well not the trouble
that a CSV file is culture depended).

To get your xml file

myDataSet.ReadXML(path)

To write your xml file

myDataset.WriteXML(path) 'however secure this so that you are sure that you
don't overwrite it direct but delete the old original as that is done.

To create it
dim myDataset as new Dataset
dim myDataTable as new DataTable
myDataset.Tables.Add(myDataTable)
myDatatable.columns.add("Book")
myDatatable.columns.add("Author")
myDatatable.columns.add("ISBN")

To load a new a row (with hundred other methods)
myDataTable.Loadrow(New object() {"MyBook","TheAuthor","ISBN"},true)

A dataset is a very sophisticated class inside ADONET, therefore look for
how to handle it to DataTable and DataRow on MSDN, or ask here or in the
ADONET newsgroup if you have a problem after investigating it.

I hope this gives some idea's.

Cor
Author
22 Jan 2006 9:20 PM
me
Show quote Hide quote
"Cor Ligthert [MVP]" <notmyfirstn***@planet.nl> wrote in message
news:epn8PJmHGHA.2064@TK2MSFTNGP09.phx.gbl...
> Me,
>
> If you use a dataset\table to read\write as XML instead of CSV than your
> problem becomes very simple. (while you have than as well not the trouble
> that a CSV file is culture depended).
>
> To get your xml file
>
> myDataSet.ReadXML(path)
>
> To write your xml file
>
> myDataset.WriteXML(path) 'however secure this so that you are sure that
> you don't overwrite it direct but delete the old original as that is done.
>
> To create it
> dim myDataset as new Dataset
> dim myDataTable as new DataTable
> myDataset.Tables.Add(myDataTable)
> myDatatable.columns.add("Book")
> myDatatable.columns.add("Author")
> myDatatable.columns.add("ISBN")
>
> To load a new a row (with hundred other methods)
> myDataTable.Loadrow(New object() {"MyBook","TheAuthor","ISBN"},true)
>
> A dataset is a very sophisticated class inside ADONET, therefore look for
> how to handle it to DataTable and DataRow on MSDN, or ask here or in the
> ADONET newsgroup if you have a problem after investigating it.
>
> I hope this gives some idea's.
>
> Cor


Thanks Cor,

This makes me wonder - is there a generic command or function that will
write out/read in the contents of a Collection or Arrayset to an XML file?
Author
23 Jan 2006 8:02 AM
Cor Ligthert [MVP]
>
> This makes me wonder - is there a generic command or function that will
> write out/read in the contents of a Collection or Arrayset to an XML file?
>
Why, the DataSet is for much data needs a better collection than an
ArraySet.

An analogy

Use a car if you need that, use a bicycle as you need that. By instance in
the city where I am born, you can better go by bicycle than by car, but you
should not use that to go out of that city. There are bicycles that you can
fold. They ride bad, and it is forever a lot of work to fold and to unfold
them.

Cor
Author
22 Jan 2006 12:54 PM
me
Hey thanks a million guys - that is really helpful - appreciate it.

Will be going ahead with your suggestions and report back!

Cheers
Author
24 Jan 2006 1:36 PM
Phill W.
"me" <c**@notvalid.com> wrote in message
news:43d1906b$0$23295$db0fefd9@news.zen.co.uk...

You need a Class ("Book") to hold information about each individual Book.

You need /another/ Class that will hold your "list" of Books.
To start with, an ArrayList would probably do.

> I have set up a class (called Book) with properties such as Title, Author,
> ISBN and can get/set them

Good.  Now add a Constructor (Sub New) so that you can create
a Book with all those properties filled in in one go, as in

Public Sub New( _
  ByVal Title as String _
, ByVal Author as String _
, ISBN as String? _
)
    ' Store each argument into the equivalent property.
End Sub

Then, as you create ach book, add it to the Arraylist, as in

Dim ABook as Book
Dim AllBooks as New ArrayList

ABook = New Book( "Title", "Author", "ISBN" )
AllBooks.Add( ABook )

> So how does one then cycle through these items when saving?

For Each eBook as Book _
In AllBooks
    ' Save Book information to File
Next

> How do we create all the instances when first loading the CSV file?

Dim sr as New StreamReader( "file" )
Dim sRecord as String _
    = sr.ReadLine

Do While Not ( sLine Is Nothing )
    ' Extract Title, Author and ISBN

    ' Create Book object
    Dim ABook as New Book( Title, Author, ISBN )

    ' Add to list of books
    AllBooks.Add( ABook )

    ' Get the next one
    sRecord = sr.ReadLine
Loop
sr.Close()

Now, using the ArrayList is only start - there's no easy way to, say,
pull out a given book by Title - you'd have to loop through each Book
in the ArrayList, but there are other Collection classes (e.g. Dictionary)
that you could use instead of ArrayList.

HTH,
    Phill  W.