tags:

views:

112

answers:

6

Hi all, I've written a CustomerCollection class, which implements the IEnumerable and IEnumerator interfaces. Now I want the CustomerCollection class object to be searchable by Where() And Find() function and also would like to get a List object of type Customer From the CustomerCollection class. Please help. Also, is the implementation of the interfaces right.

public class Customer
{
    private int _CustomerID;
    private string _CustomerName;

    public Customer(int customerID)
    {
        this._CustomerID = customerID;
    }

    public int CustomerID
    {
        get
        {
            return _CustomerID;
        }
        set
        {
            _CustomerID = value;
        }
    }

    public string CustomerName
    {
        get
        {
            return _CustomerName;
        }
        set
        {
            _CustomerName = value;
        }
    }
}

public class CustomerController
{
    public ArrayList PopulateCustomer()
    {
        ArrayList Temp = new ArrayList();

        Customer _Customer1 = new Customer(1);
        Customer _Customer2 = new Customer(2);

        _Customer1.CustomerName = "Soham Dasgupta";
        _Customer2.CustomerName = "Bappa Sarkar";

        Temp.Add(_Customer1);
        Temp.Add(_Customer2);

        return Temp;
    }
}

public class CustomerCollection : IEnumerable, IEnumerator
{
    ArrayList Customers = null;
    IEnumerator CustomerEnum = null;

    public CustomerCollection()
    {
        this.Customers = new CustomerController().PopulateCustomer();
        this.CustomerEnum = Customers.GetEnumerator();
    }

    public void SortByName()
    {
        this.Reset();
    }

    public void SortByID()
    {
        this.Reset();
    }

    public IEnumerator GetEnumerator()
    {
        return (IEnumerator)this;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return (IEnumerator)this;
    }

    public void Reset()
    {
        CustomerEnum.Reset();
    }

    public bool MoveNext()
    {
        return CustomerEnum.MoveNext();
    }

    public object Current
    {
        get
        {
            return (Customer)CustomerEnum.Current;
        }
    }

}
+4  A: 

You can call Cast<Customer>() on your IEnumerable which will give you an IEnumerable<Customer>, or just implement IEnumerable<Customer> to begin with. LINQ is almost entirely hooked into IEnumerable<T>, not IEnumerable. Once you did that you'd get all the LINQ to objects goodness for free.

Matt Greer
You should probably not cache your enumerator either, but instead return a new one with each call to `GetEnumerator`, each call to `GetEnumerator` should return an object capable of enumerating the collection without mucking with anything else. Having two enumerations share the same enumerator is problematic.
Matt Greer
+1  A: 

This will do what you want. Note, I have abstracted out the IEnumerable to make it reusable and reduced the complexity of all of the other classes.

//Write your Test first
public class Test
{
    public void TestEnumerator()
    {
        var customers = new CustomerCollection();
        var qry = 
            from c in customers
            select c;

        foreach (var c in qry)
        {
            Console.WriteLine(c.CustomerName);
        }

        //Create a new list from the collection:
        var customerList = new List<Customer>(customers);
    }
}

public abstract class MyColl<T> : IEnumerable<T>
{
    protected T[] Items;
    public IEnumerator<T> GetEnumerator()
    {
        foreach (T item in Items)
        {
            yield return item;
        }
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public class Customer
{
    public Customer(int customerID)
    {
        CustomerID = customerID;
    }
    public int CustomerID { get; set; }
    public string CustomerName { get; set; }
}

public class CustomerController
{
    public Customer[] PopulateCustomer() {
       return new [] {new Customer(1) {CustomerName = "Soham Dasgupta"},
                      new Customer(2) {CustomerName = "Bappa Sarkar"}};
    }
}

public class CustomerCollection : MyColl<Customer>
{

    public CustomerCollection()
    {
        Items = new CustomerController().PopulateCustomer();
    }
}
Daniel Dyson
+2  A: 

I recommend to use OfType<T>() instead of Cast<T>() because if your collection contains T1 and T2, collection.Cast<T1>() will throw an error while collection.OfType<T1>() will return IEnumerable<T1> contains only instances of T1 not T2

abatishchev
Ah, but is it necessarily a bad thing to throw an exception when there's an unexpected element in there?
Kirk Woll
@Kirk: Depending on a case, of course. 99.99% of time where I use `OfType` is converting all this .NET 2.0 built-in, non-generic collections like ControlCollection, ElementCollection, so on, so on, to IEnumerable so I'm not sure what does they exactly contain so an addition check is ok
abatishchev
@abatishchev, well, the name of his class is called "CustomerCollection" so it would seem startling (and worthy of an Exception) if it were to contain anything else. :)
Kirk Woll
+1  A: 
public class CustomerController 
{ 
    public List<Customer> PopulateCustomer() 
    { 
        List<Customer> Temp = new ArrayList(); 

        Customer _Customer1 = new Customer(1); 
        Customer _Customer2 = new Customer(2); 

        _Customer1.CustomerName = "Soham Dasgupta"; 
        _Customer2.CustomerName = "Bappa Sarkar"; 

        Temp.Add(_Customer1); 
        Temp.Add(_Customer2); 

        return Temp; 
    } 
} 


public class CustomerCollection : List<Customer>
{  
    List<Customer> Customers = new List<Customer>();  


    public CustomerCollection()  
    {  
        this.Customers = new CustomerController().PopulateCustomer();  
    }    

}  
chugh97
+1  A: 
new List<Customer>(myCustomerEnumerator);
manixrock
+1  A: 

The recommended base class to use for creating your own collection implementations is System.Collections.ObjectModel.Collection<T>

(from MSDN)
This base class is provided to make it easier for implementers to create a custom collection. Implementers are encouraged to extend this base class instead of creating their own.

public class CustomerCollection : Collection<Customer>
{
}
Cameron MacFarland