Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Collections Questions

Status
Not open for further replies.

ChewDoggie

Programmer
Mar 14, 2005
604
US
Hello All,

I'm a newbie and am trying to get my head around Generic Collections. This is just practice, so no biggy on the response times. My Question: how do I retrieve a particular Adult from the following Adults list ?

I've created this first generic class called Adults (plural):

Code:
using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCollections
    {
    public class Adults<T> : IEnumerable<T>, ICollection<T>
        {
        private List<T> TheseAdults = new List<T>();

        public Adult GetAdult( int Memberid )
            {
            // This Method is unfinished
            Adult A = new Adult();

            return A;
            }

        public Adults()
            {

            }

        #region IEnumerable<T> Members

        public IEnumerator<T> GetEnumerator()
            {
            throw new NotImplementedException();
            }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
            throw new NotImplementedException();
            }

        #endregion

        #region ICollection<T> Members

        public void Add( T item )
            {
            TheseAdults.Add( item );
            }

        public void Clear()
            {
            for ( int i = 0;i <= TheseAdults.Count - 1;i++ )
                {
                TheseAdults.Remove( TheseAdults[i] );
                }
            }

        public bool Contains( T item )
            {
            return TheseAdults.Contains( item );
            }

        public void CopyTo( T[] array, int arrayIndex )
            {
            TheseAdults.CopyTo( array, arrayIndex );
            }

        public int Count
            {
            get
                {
                return TheseAdults.Count;
                }
            }

        public bool IsReadOnly
            {
            get 
                {
                return false;
                }
            }

        public bool Remove( T item )
            {
            return TheseAdults.Remove( item );
            }

        #endregion
        }
    }

Then I created this other class called Adult (singular):

Code:
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Data;
using System.Linq;

namespace MyCollections
    {
    public class Adult
        {
        private string fname;
        private string lname;
        private string addr;
        private string city;
        private string state;
        private string phone;
        private DateTime expdate;
        private string ConnStr = @"Data Source=.\SQLEXPRESS;AttachDbFilename='C:\Program Files\Microsoft SQL Server\MSSQL10.CHEWDOGGIE\MSSQL\DATA\library.mdf';Integrated Security=True;Connect Timeout=30;User Instance=True";

        public string City
            {
            get
                {
                return city;
                }
            set
                {
                city = value;
                }
            }
        public string FirstName
            {
            get
                {
                return fname;
                }
            set
                {
                fname = value;
                }
            }
        public string LastName
            {
            get
                {
                return lname;
                }
            set
                {
                lname = value;
                }
            }
        public string Address
            {
            get
                {
                return addr;
                }
            set
                {
                addr = value;
                }
            }
        public string State
            {
            get
                {
                return state;
                }
            set
                {
                state = value;
                }
            }
        public string PhoneNumber
            {
            get
                {
                return phone;
                }
            set
                {
                phone = value;
                }
            }
        public DateTime ExpirationDate
            {
            get
                {
                return expdate;
                }
            set
                {
                expdate = value;
                }
            }
        public Adult()
            {
            }
        public Adult(int MemberID)
            {
            try
                {
                using ( SqlConnection cnn = new SqlConnection( ConnStr ) )
                    {
                    using ( SqlCommand cmd = new SqlCommand( "GetMemberFromMemberid", cnn ) )
                        {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue( "@membernum", MemberID );
                        cnn.Open();
                        SqlDataReader reader = cmd.ExecuteReader();
                        while ( reader.Read() )
                            {
                            this.FirstName = reader["FName"].ToString();
                            this.LastName = reader["LName"].ToString();
                            this.Address = reader["Addr"].ToString();
                            this.City = reader["City"].ToString();
                            this.State = reader["State"].ToString();
                            this.PhoneNumber = reader["Phone"].ToString();
                            this.ExpirationDate = Convert.ToDateTime( reader["ExpirationDate"].ToString() );
                            }
                        }
                    }
                }
            catch ( Exception ex )
                {
                throw new Exception( ex.Message );
                }
            }
        }
    }

And the following lines of code produce a Message Box that says "52"...which is correct. There are 52 objects being added to the Adults object. As you can see, I'm calling the non-default contructor for the Adult class and for the purposes of this exercise, I'm not Disposing the Adult object each time I create it.

Code:
        private void Form1_Load( object sender, EventArgs e )
            {
            Adults<Adult> AdultList = new Adults<Adult>();
            for ( int x = 1;x <= 100;x++ )
                {
                Adult A = new Adult( x );
                if ( A.LastName != null )
                    {
                    AdultList.Add( A );
                    }
                }
            MessageBox.Show( AdultList.Count.ToString() );
            }

I'm using List as my vehicle of choice. If anyone can shed some more light on a better choice, I'm all eyes.

Thanks !

Chew


10% of your life is what happens to you. 90% of your life is how you deal with it.
 
In your example, to get a particular adult you would use the member id like this:
Code:
Adult myAdult = AdultList.GetAdult[29];

To help you get your head around it all, here's an example of how it could be used: (although it doesn't really fit your example, sorry.)

Adult would be an abstract base class.
AdultDog, AdultCat, AdultMouse would all inherit from Adult.
Code:
var dogs = new Adults<AdultDog>();
var cats = new Adults<AdultCat>();
var mice = new Adults<AdultMouse>();

SayHelloToAdults(dogs);
SayHelloToAdults(cats);
SayHelloToAdults(mice);

Code:
public SayHelloToAdults(Adults adults)
{
    foreach (Adult adult in adults)
    {
        MessageBox.Show("Hello " + adult.FirstName);
    } 
    
}
 
OK, I see what you mean in your example. However, my "GetAdult" method is not coded to return an Adult from the Adults list and I wanted to see how that would be coded.

Thanks!

Chew


10% of your life is what happens to you. 90% of your life is how you deal with it.
 
OK, well I progressed a little. I've added some code to the Adults class so that it now looks like this:

Code:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;

namespace MyCollections
    {
    public class Adults<T> : IEnumerable<T>, ICollection<T>, IComparable
        {
        private Node head;
        private List<T> TheseAdults = new List<T>();

        private class Node
            {
            private Node next;
            //T as private member data type:
            private T data;
            //T used in non-generic constructor:

            // non-default constructor
            public Node( T t )
                {
                next = null;
                data = t;
                }


            public Node Next
                {
                get { return next; }
                set { next = value; }
                }

            //T as return type of property:
            public T Data
                {
                get { return data; }
                set { data = value; }
                }
            }

        public Adults()
            {
            head = null;
            }

        #region IEnumerable<T> Members

        public IEnumerator<T> GetEnumerator()
            {
            Node Current = head;
            while ( Current != null )
                {
                yield return Current.Data;
                Current = Current.Next;
                }
            }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator()
            {
            throw new NotImplementedException();
            }

        #endregion

        #region ICollection<T> Members

        public void Add( T item )
            {
            TheseAdults.Add( item );
            }

        public void Clear()
            {
            for ( int i = 0;i <= TheseAdults.Count - 1;i++ )
                {
                TheseAdults.Remove( TheseAdults[i] );
                }
            }

        public bool Contains( T item )
            {
            return TheseAdults.Contains( item );
            }

        public void CopyTo( T[] array, int arrayIndex )
            {
            TheseAdults.CopyTo( array, arrayIndex );
            }

        public int Count
            {
            get
                {
                return TheseAdults.Count;
                }
            }

        public bool IsReadOnly
            {
            get 
                {
                return false;
                }
            }

        public bool Remove( T item )
            {
            return TheseAdults.Remove( item );
            }

        #endregion

        #region IComparable Members

        public int CompareTo( object obj )
            {
            return 0;
            }

        #endregion
        }
    }

But the following foreach loop doesn't produce ANY MessageBoxes:

Code:
        private void Form1_Load( object sender, EventArgs e )
            {
            Adults<Adult> AdultList = new Adults<Adult>();
            for ( int x = 1;x <= 100;x++ )
                {
                Adult A = new Adult( x );
                if ( A.LastName != null )
                    {
                    AdultList.Add( A );
                    }
                }
            MessageBox.Show( AdultList.Count.ToString() );
            foreach ( Adult B in AdultList )
                {
                MessageBox.Show( B.FirstName + ' ' + B.LastName );
                }
            }



10% of your life is what happens to you. 90% of your life is how you deal with it.
 
Have you tried stepping through it in debug mode?

Check that your sql command is returning what you expect. Have the members got data in the last name column?

By the way a separate issue I notice is in your exception handling - if your re-throwing an exception when caught don't use:
Code:
throw new Exception(ex.message);
Instead use:
Code:
throw;
The former way could hide important information, inner exceptions, etc.
 
OK, I got this working now, with one exception noted below.

Code:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Collections;
using System.Linq;

namespace MyCollections
    {
    public class Adults<T> : IList<T>, IEnumerable<T>, ICollection<T> where T : class, IDisposable
        {
        private List<T> TheseAdults = new List<T>();

        public Adults()
            {

            }

        #region IEnumerable<T> Members
        public IEnumerator<T> GetEnumerator()
            {
            return ( TheseAdults.GetEnumerator() );
            }
        #endregion

        #region IEnumerable Members
        IEnumerator IEnumerable.GetEnumerator()
            {
            return ( TheseAdults.GetEnumerator() );
            }
        #endregion

        #region Private Members
        private void Delete( T item )
            {
            item.Dispose();
            }
        #endregion

        #region ICollection<T> Members
        public void Add( T item )
            {
            TheseAdults.Add( item );
            }

        public void Clear()
            {
            int AdultCount = TheseAdults.Count;
            for ( int i = 0;i < AdultCount;i++ )
                {
                Delete( TheseAdults[i] );
                }
            TheseAdults.Clear();
            }

        public bool Contains( T item )
            {
            return TheseAdults.Contains( item );
            }

        public void CopyTo( T[] array, int arrayIndex )
            {
            TheseAdults.CopyTo( array, arrayIndex );
            }

        public int Count
            {
            get
                {
                return TheseAdults.Count;
                }
            }

        public bool IsReadOnly
            {
            get 
                {
                return false;
                }
            }

        public bool Remove( T item )
            {
            return TheseAdults.Remove( item );
            }
        #endregion

        #region IList<T> Members
        public int IndexOf( T item )
            {
            return TheseAdults.IndexOf( item );
            }

        public void Insert( int index, T item )
            {
            TheseAdults.Insert( index, item );
            }

        public void RemoveAt( int index )
            {
            Delete( this[index] );
            TheseAdults.RemoveAt( index );
            }

        public T this[int index]
            {
            get
                {
                return TheseAdults[index];
                }
            set
                {
                TheseAdults[index] = value;
                }
            }
        #endregion
        }
    }

This works good. However, when I created a list of adults, I attempted to create a copy like this:

Code:
        private void Form1_Load( object sender, EventArgs e )
            {
            Adults<Adult> AdultList = new Adults<Adult>();
            Adults<Adult> SecondList = new Adults<Adult>();
            string LeftChar = string.Empty;
            for ( int x = 1;x <= 500;x++ )
                {
                Adult A = new Adult( x );
                AdultList.Add( A );
                A.Dispose();
                }
            [b]SecondList = AdultList;[/b]
            MessageBox.Show( "FIRST LIST COUNT: " + AdultList.Count.ToString() + "\nSECOND LIST COUNT: " + SecondList.Count.ToString() );
            foreach ( Adult B in AdultList )
                {
                SecondList.Remove( B );
                }
            MessageBox.Show( "FIRST LIST COUNT: " + AdultList.Count.ToString() + "\nSECOND LIST COUNT: " + SecondList.Count.ToString() );
            }

But it barfed on the next foreach loop, as if it created a reference to the first collection, rather than a copy, which I thought was interesting.

How does one copy a collection ?

Chew


10% of your life is what happens to you. 90% of your life is how you deal with it.
 
It will create a reference that way - you need to implement a Clone() method of some kind.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top