I followed the article here and the sample code given in it.
What I am trying to implement is pretty straightfoward. I do have a fair understanding about collections and enumerators. However, what I don't understand is that even though there is hardly any difference in the way I have implemented the code as compared to how it is implemented in the given article, why I am getting an error.
Only difference in the implementation is that the sample code uses T (generic) whereas I am using a class named Address while implementing the custom Addresses collection class.
The code is pretty straightfoward. I have the following classes in the project.
- Contact class
- Addresses class (Implements custom collection and inherits from ICollection)
- Address class
- AddressEnumerator
What I wish to achieve is the Dataset like functionality where we can use a syntax like: Dataset ds = new Dataset();
Ds.Tables[0]....blah blah blah.
I get a compile time error in the following method of the AddressEnumerator.cs class. Error: cannot apply indexing with [] to an expression of type ConsoleApplication2.Addresses (Addresses class implements an ICollection)
Compile time error occurs in the following statement: _current = _collection[index];
public bool MoveNext()
{
if(++index >= _collection.Count)
{
return false;
}
else
{
_current = _collection[index];
}
return true;
}
Source code:
//following code snippet does not traverse the collection
foreach (Address a in c.Addresses)
{
Console.WriteLine(a.Street);
}
Program.cs
using System;
using System.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
//RenderTimeSheet();
Address ad = new Address();
ad.Street = "Hollywood";
ad.City = "LA";
ad.State = "California";
ad.ZipCode = "93494";
ad.Country = "USA";
using (Contact c = new Contact(ad))
{
c.FirstName = "John";
c.LastName = "Doe";
Console.WriteLine(c.FirstName);
Console.WriteLine(c.LastName);
foreach (Address a in c.Addresses)
{
Console.WriteLine(a.Street);
}
}
Console.ReadKey();
}
}
Contact.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
namespace ConsoleApplication2
{
public class Contact : IDisposable
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Addresses Addresses { get; set; }
public Contact(Address a)
{
Addresses = new Addresses(a);
}
public Contact()
{
}
public void Dispose()
{
Console.Write("Disposing off...");
}
}
}
Addresses.cs
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
public class Addresses : ICollection<Address>
{
private IList<Address> _lstAddress;
protected bool _IsReadOnly;
public Addresses(Address _a)
{
_lstAddress = new List<Address>();
}
public void Add(Address item)
{
_lstAddress.Add(item);
}
public void Clear()
{
_lstAddress.Clear();
}
public bool Contains(Address item)
{
foreach(Address a in _lstAddress)
{
if(a.Street == item.Street)
{
return true;
}
}
return false;
}
public void CopyTo(Address[] array, int arrayIndex)
{
throw new Exception("Not valid for this implementation.");
}
public int Count
{
get { return _lstAddress.Count; }
}
public bool IsReadOnly
{
get { return _IsReadOnly; }
}
public bool Remove(Address item)
{
bool result = false;
for (int i = 0; i < _lstAddress.Count; i++)
{
Address obj = (Address)_lstAddress[i];
if(obj.Street == item.Street)
{
_lstAddress.RemoveAt(i);
result = true;
break;
}
}
return result;
}
public IEnumerator<Address> GetEnumerator()
{
return new AddressEnumerator(this);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
//throw new NotImplementedException();
return this.GetEnumerator();
}
}
}
Address.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public string Country { get; set; }
}
}
AddressEnumerator.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
public class AddressEnumerator : IEnumerator<Address>
{
protected Addresses _collection;
protected int index;
protected Address _current;
public AddressEnumerator()
{
}
public AddressEnumerator(Addresses collection)
{
_collection = collection;
index = -1;
_current = default(Address);
}
public Address Current
{
get
{
return _current;
}
}
public void Dispose()
{
_collection = null;
_current = default(Address);
index = -1;
}
object System.Collections.IEnumerator.Current
{
get
{
return _current;
}
}
public bool MoveNext()
{
if(++index >= _collection.Count)
{
return false;
}
else
{
_current = _collection[index];
}
return true;
}
public void Reset()
{
throw new NotImplementedException();
}
}
}
this is a direct and short solution to your problem, but it is not a "complete clean" solution, also the coding style of the complete implementation should be changed. there are more effective ways implementing enumerable interfaces ...
change the line
to
but you also need to change the access modifier
for example to