Ошибка при реализации IEnumerator
Я следовал за этой статьей и приведенным в ней примером кода.
То, что я пытаюсь реализовать, довольно просто. У меня есть четкое представление о коллекциях и счетчиках. Однако чего я не понимаю, так это того, что, несмотря на то, что способ реализации кода практически не отличается от того, как он реализован в данной статье, я получаю сообщение об ошибке.
Единственное отличие в реализации состоит в том, что в примере кода используется T (универсальный), тогда как я использую класс с именем Address при реализации пользовательского класса коллекции адресов.
Код довольно прост. У меня есть следующие классы в проекте.
- Контактный класс
- Класс адресов (реализует пользовательскую коллекцию и наследует от ICollection)
- Адресный класс
- AddressEnumerator
Чего я хочу добиться, так это функциональности, подобной Dataset, где мы можем использовать такой синтаксис, как: Dataset ds = new Dataset ();
Ds.Tables [0].... бла-бла-бла.
Я получаю ошибку времени компиляции в следующем методе класса AddressEnumerator.cs. Ошибка: невозможно применить индексирование с помощью [] к выражению типа ConsoleApplication2.Addresses (класс Addresses реализует ICollection)
Ошибка времени компиляции возникает в следующем операторе: _current = _collection[index];
public bool MoveNext()
{
if(++index >= _collection.Count)
{
return false;
}
else
{
_current = _collection[index];
}
return true;
}
Исходный код:
// следующий фрагмент кода не пересекает коллекцию
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();
}
}
}
2 ответа
Это прямое и краткое решение вашей проблемы, но это не "полностью чистое" решение, также следует изменить стиль кодирования полной реализации. Есть более эффективные способы реализации перечислимых интерфейсов...
изменить линию
_current = _collection[index];
в
_current = _collection._lstAddress[index];
но вам также нужно изменить модификатор доступа
private IList<Address> _lstAddress
например, чтобы
internal IList<Address> _lstAddress
Причина того, что пример кода работает, а ваш нет, заключается в том, что пример кода класса BusinessObjectCollection
включает в себя это:
public virtual T this[int index]
{
get
{
return (T)_innerArray[index];
}
set
{
_innerArray[index] = value;
}
}
который обеспечивает оператор индекса []
что ваш код не хватает.
Если вы добавите это к вашему Addresses
класс (меняется _innerArray
в _lstAddress
) тогда должно работать, я думаю.