在自定义集合上实现IEnumerable,它与LINQ的参与

时间:2016-10-02 06:13:44

标签: c# .net linq ienumerable ienumerator

虽然这个问题似乎是多余的,并且每个人都谈论它,但我保证它不是,或者最后关于我所遇到的问题,没有多少人会如何谈论这个问题。

那是怎么回事?

我想在我的Collection中实现IEnumerable和IEnumerator。我之前做过这个...,为什么我还在这里?我在这里是因为我不确定Linq如何处理数据。实现这一目标的最佳做法是什么。

虽然大多数人总是指向用户实现集合的示例,它自己包含列表或类型,但我确实实现了一个用于解析数据的2类,并在这些数据下进行细分。 每个类都与IEnumerable非常相似,所以昨天我说,嘿,它就像枚举器一样,为什么我不把C#关键字的强大功能带到我的类中,添加IEnumerator和IEnumerable接口呢?

所以我这样做了。但我的类是持有数据和光标的人,而不是其中的另一个集合,并且它没有说例如: myList.GetEnumerator返回新的Enumerator实例,但它本身是枚举器和可枚举的,所以:

我的问题 linq使用enumerator.reset和其他东西吗?是否设法将数据保存在他们所在的位置?我不这么认为,但我想确定,如果我应该返回我班级的新实例,或者只是指向this

这是我当前的代码,我给它一个新类的实例版本。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.VisualBasic;

namespace GabrielWinFormTest.Parsers
{
    [DebuggerNonUserCode]
    public class LineReader:IEnumerator<string>, IEnumerable<string>
    {
        private readonly string _data;
        private int _nextValuePosition;

        //Properties
        object IEnumerator.Current { get { return Current; } }
        public string Current { get; private set; }

        public LineReader(string data)
        {
            _data = data;
            Reset();
        }

        public void Reset()
        {
            _nextValuePosition = 1;
            Current = string.Empty;
        }

        public bool MoveNext()
        {
            bool result;

            if (_data == null) throw new Exception("Data is null or empty");

            if (_nextValuePosition > Strings.Len(_data))
            {
                result = false; //Return No Data Signature
                Current = string.Empty;
            }
            else
            {
                var nextPos = GetPositionOfLineFeed(_data, _nextValuePosition);
                if (nextPos == 0)
                {
                    result = false; //Returns No Data Signature
                }
                else
                {
                    Current = GetLineAtPosition(_data, nextPos);
                    _nextValuePosition = nextPos + Strings.Len(Current);
                    result = true; //Returns Has Data Signature
                }
            }
            return result;
        }

        /// <summary>
        /// Return Specific Line, Without Moving Cursor (Generate New LineReader Inside Itself)
        /// </summary>
        /// <param name="position">The position of segment (start by 0)</param>
        /// <returns></returns>
        public string GetLineAt(int position)
        {
            var lineReader = new LineReader(_data);
            var i = 0;
            while (lineReader.MoveNext() && i++ < position)
            {
            }

            return lineReader.Current;
        }

        //Get Position before Next Line (Searching for char(13))
        private int GetPositionOfLineFeed(string str, int lastPosition)
        {
            if (lastPosition == 0) throw new Exception("lastPosition cannot be less than 1");

            int result = 0;
            for (int i = lastPosition; i <= Strings.Len(str); i++)
            {
                if (Strings.Mid(str, i, 1) != Strings.Chr(13).ToString())
                {
                    result = i;
                    break;
                }
            }
            return result;
        }

        //Get non-spaced Value At Given Position
        private string GetLineAtPosition(string str, int position)
        {
            if (position == 0) throw new Exception("position cannot be less than 1");

            string result = string.Empty;
            int i;

            for (i = position; i <= Strings.Len(str); i++)
            {
                if (Strings.Mid(str, i, 1) == Strings.Chr(13).ToString())
                {
                    result = Strings.Mid(str, position, i - position);
                    break;
                }
            }

            //If The value placed at the end of line ( xyz at "??????????????xyz")
            if (i > Strings.Len(str))
                result = Strings.Mid(str, position, i - position);

            return result;
        }

        public void Dispose()
        {
            //Microsoft left it blank in it's sample, so i can do it too :-/
        }

        public IEnumerator<string> GetEnumerator()
        {
            return new LineReader(_data);
        }

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

我的逻辑说我是对的,但我想知道背后其他人的逻辑。

0 个答案:

没有答案