Не понимаю IEnumerable <T> - PullRequest
       24

Не понимаю IEnumerable <T>

1 голос
/ 02 сентября 2010

У меня много проблем с моим кодом.При компиляции я получаю следующую ошибку:


«Ecommerce.DataHelpers.ProductNodeLoader» не реализует элемент интерфейса «System.Collections.IEnumerable.GetEnumerator ()».«Ecommerce.DataHelpers.ProductNodeLoader.GetEnumerator ()» не может реализовать «System.Collections.IEnumerable.GetEnumerator ()», поскольку у него нет соответствующего возвращаемого типа «System.Collections.IEnumerator».


Я не уверен, как решить эту проблему, поэтому теперь я должен спросить вас, ребята!

КОД:

namespace Ecommerce.DataHelpers
{
    public class ProductNodeLoader<T> : IEnumerable<T>
    {
        private ISqlHelper sqlHelper;
        private IRecordsReader nodeReader;

        public List<T> list = new List<T>();

        // load all products from given company
        public IEnumerator<T> GetEnumerator()
        {
            int companyId = 2;
            try
            {
                sqlHelper = DataLayerHelper.CreateSqlHelper(GlobalSettings.DbDSN);
                nodeReader = sqlHelper.ExecuteReader(@"
                    SELECT * FROM eCommerceNodes WHERE companyId = @companyId)
                    ", sqlHelper.CreateParameter("@companyId", companyId));

            }
            catch (Exception e)
            {
                Log.Add(LogTypes.Custom, -1, e.InnerException.ToString());
                yield break;
            }

            if (nodeReader.HasRecords)
            {
                while(nodeReader.Read())
                {
                    ProductNode node = new ProductNode();
                    node.id = nodeReader.Get<int>("id");
                    node.parentId = nodeReader.Get<int>("parentId");
                    node.companyId = nodeReader.Get<int>("companyId");
                    node.path = nodeReader.Get<string>("path");
                    node.sortOrder = nodeReader.Get<string>("sortOrder");
                    node.text = nodeReader.Get<string>("text");
                    node.nodeType = nodeReader.Get<int>("nodeType");

                    list.Add(node);

                }
                nodeReader.Close();

            }
            else
            {
                throw new ApplicationException("No products to load");
            }

            return list;
        }

    }
}

Я прошу прощения за плохое редактирование!

1 Ответ

7 голосов
/ 02 сентября 2010

Вы также пытаетесь реализовать неуниверсальный тип IEnumerable, так как IEnumerable<T> расширяет его. К счастью, это легко:

// Along with the existing using directives
using System.Collections;
...

// In the implementing class
IEnumerator IEnumerable.GetEnumerator()
{
    return GetEnumerator();
}

Обратите внимание, что вы должны использовать явную реализацию интерфейса как минимум для одного из двух GetEnumerator() методов, которые вам нужно реализовать, поскольку они имеют одинаковую подпись (одно и то же имя, без параметров), но разные типы возврата. К счастью, возвращаемое значение универсальной версии прекрасно подходит для неуниверсальной версии, поэтому обычно используется вышеуказанный шаблон.

РЕДАКТИРОВАТЬ: Как правильно замечает Джош в комментариях, у вас есть и другие проблемы:

  • У вас не должно быть return list; в конце кода, если только вы не удалили yield break; ранее (и не изменили его на return list.GetEnumerator();). Если вы хотите сохранить свой код как блок итератора, вы должны использовать yield return, чтобы получить каждый созданный вами узел.
  • Вы должны давать экземпляры T - тогда как вы создаете экземпляры ProductNode. Возможно, вам следует реализовать IEnumerable<ProductNode> вместо IEnumerable<T> и сделать ваш класс не универсальным?
  • Ваш код будет поддерживать соединение SQL открытым до тех пор, пока вызывающая сторона решит выполнить итерацию по нему. Это может быть или не быть проблемой - но это стоит иметь в виду.
  • Вы должны использовать оператор using, чтобы убедиться, что ваш nodeReader удаляется при ошибке (при условии, что вызывающая сторона, конечно, IEnumerator<T> удаляет)
  • Ваше открытое list поле - плохая идея ... почему вы вообще сделали его переменной экземпляра?
...