不理解IEnumerable <t> </t>

时间:2010-09-02 13:07:36

标签: c# .net ienumerable

我的代码遇到了很多问题。当我编译时,我收到以下错误:


'Ecommerce.DataHelpers.ProductNodeLoader'未实现接口成员'System.Collections.IEnumerable.GetEnumerator()'。 'Ecommerce.DataHelpers.ProductNodeLoader.GetEnumerator()'无法实现'System.Collections.IEnumerable.GetEnumerator()',因为它没有匹配的返回类型'System.Collections.IEnumerator'。


我不知道如何解决这个问题所以现在我不得不问你们!

CODE:

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 个答案:

答案 0 :(得分:7)

您正在尝试实施非通用IEnumerable类型,因为IEnumerable<T>扩展了它。幸运的是,这很容易:

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

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

请注意,您必须使用explicit interface implementation至少一个您需要实现的两个GetEnumerator()方法,因为它们具有相同的签名(同名,不参数)但不同的返回类型。幸运的是,泛型版本的返回值可以用于非泛型版本,这就是通常使用上述模式的原因。

编辑:正如乔希在评论中正确指出的那样,你也有其他问题:

  • 除非您先删除return list;(并将其更改为yield break;),否则代码末尾不应该有return list.GetEnumerator();。如果要将代码保留为迭代器块,则应使用yield return来生成您创建的每个节点。
  • 你应该产生T的实例 - 而你正在构建ProductNode的实例。也许您应该实际使用IEnumerable<ProductNode>而不是IEnumerable<T>,并使您的类非通用?
  • 只要调用者决定对其进行迭代,您的代码就会保持SQL连接处于打开状态。这可能是也可能不是问题 - 但值得记住。
  • 您应该使用using语句确保您的nodeReader出错(假设来电者当然处理了IEnumerator<T>
  • 您的公开list字段是一个坏主意...为什么要让它成为实例变量?