c# - IEnumerable 无法计算表达式,因为当前线程处于堆栈溢出状态

标签 c# enumerable

我正在编写一个获取 Wireshark 文件(Pcap、Snopp、Pcapng...)的应用程序,打开它并读取所有数据包。

我的基类:

public abstract class WiresharkFile
{
   ...
}

所有子类都实现了IEnumerable:

public class Libpcap : WiresharkFile, IDisposable, IEnumerable<WiresharkFilePacket>
{
    ....
}

现在,当我创建对象时,我的代码会自动识别它,然后创建当前的 object 类型,例如:

wiresharkFile = new Libpcap(file);

然后当我想遍历我的文件并读取数据包时:

foreach (var packet in wiresharkFile)
{
   ...
}

我收到这个错误:

foreach statement cannot operate on variables of type WiresharkFile' because WiresharkFile' does not contain a public definition for 'GetEnumerator'

所以我在 WiresharkFile 基类中添加了这个函数:

public IEnumerator<WiresharkFilePacket> GetEnumerator()
{
    return GetEnumerator();
}

现在我收到此错误 StackOverflowException:

Cannot evaluate expression because the current thread is in a stack overflow state.

编辑

public class Libpcap : WiresharkFile, IDisposable, IEnumerable<WiresharkFilePacket>
{
    private BinaryReader binaryReader;
    private Version version;
    private uint snaplen;
    private int thiszone;
    private uint sigfigs;
    private LibpcapLinkType linktype;
    private long basePos;
    private bool byteSwap;
    private static uint MAGIC = 0xa1b2c3d4;
    private static uint MAGIC_ENDIAN = 0xd4c3b2a1;

    public Libpcap(string path) : this(new FileStream(path, FileMode.Open, FileAccess.Read))
    {
        FileName = path;
        binaryReader = new BinaryReader(new FileStream(path, FileMode.Open, FileAccess.Read));
    }        

    public void Close()
    {
        binaryReader.Close();
    }

    public enum LibpcapLinkType
    {
        Null,
        Ethernet,
        ExpEthernet,
        AX25,
        ProNet,
        Chaos,
        TokenRing,
        ArcNet,
        Slip,
        Ppp,
        Fddi
    }

    public Libpcap(Stream s)
    {
        binaryReader = new BinaryReader(s);
        uint magic = binaryReader.ReadUInt32();

        ushort major = binaryReader.ReadUInt16();
        ushort minor = binaryReader.ReadUInt16();

        thiszone = binaryReader.ReadInt32();
        sigfigs = binaryReader.ReadUInt32();
        snaplen = binaryReader.ReadUInt32();
        uint ltype = binaryReader.ReadUInt32();

        if (byteSwap)
        {
            major = ByteSwap.Swap(major);
            minor = ByteSwap.Swap(minor);
            thiszone = ByteSwap.Swap(thiszone);
            snaplen = ByteSwap.Swap(snaplen);
            ltype = ByteSwap.Swap(ltype);
        }

        version = new Version(major, minor);
        linktype = (LibpcapLinkType)((int)ltype);
        basePos = binaryReader.BaseStream.Position;

        protected override WiresharkFilePacket ReadPacket()
        {
            if (binaryReader.BaseStream.Position < binaryReader.BaseStream.Length)
            {
                int secs = binaryReader.ReadInt32();
                int usecs = binaryReader.ReadInt32();
                uint caplen = binaryReader.ReadUInt32();
                uint len = binaryReader.ReadUInt32();
                if (byteSwap)
                {
                    secs = ByteSwap.Swap(secs);
                    usecs = ByteSwap.Swap(usecs);
                    caplen = ByteSwap.Swap(caplen);
                    len = ByteSwap.Swap(len);
                }

                DateTime timeStamp = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds((Double)secs).AddMilliseconds((Double)usecs / 1000);
                byte[] data = binaryReader.ReadBytes((int)caplen);

                return new WiresharkFilePacket(timeStamp, data);
            }
            else
                return null;
        }

        public Version Version
        {
            get
            {
                return version;
            }
        }

        public uint MaximumCaptureLength
        {
            get
            {
                return snaplen;
            }
        }

        public int TimezoneOffset
        {
            get
            {
                return thiszone;
            }
        }

        public uint SignificantFigures
        {
            get
            {
                return sigfigs;
            }
        }

        public LibpcapLinkType LinkType
        {
            get
            {
                return linktype;
            }
        }

        public void Rewind()
        {
            binaryReader.BaseStream.Position = basePos;
        }

        public override string ToString()
        {
            string endianness;

            if (BitConverter.IsLittleEndian)
            {
                if (byteSwap)
                    endianness = "Big";
                else
                    endianness = "Little";
            }
            else
            {
                if (byteSwap)
                    endianness = "Little";
                else
                    endianness = "Big";
            }

            return String.Format("{0}-endian {1} capture, pcap version {2}", endianness, linktype.ToString(), version.ToString());
        }

        public void Dispose()
        {
            binaryReader.Close();
        }

        public class PacketEnumerator : IEnumerator<WiresharkFilePacket>
        {
            private Libpcap file;
            private WiresharkFilePacket currentPacket = null;

            public PacketEnumerator(Libpcap file)
            {
                this.file = file;
            }

            #region IEnumerator<PcapPacket> Members

            public WiresharkFilePacket Current
            {
                get { return currentPacket; }
            }

            #endregion

            #region IDisposable Members

            public void Dispose()
            {
            }

            #endregion

            #region IEnumerator Members

            object System.Collections.IEnumerator.Current
            {
                get { return currentPacket; }
            }

            public bool MoveNext()
            {
                currentPacket = file.ReadPacket();
                return currentPacket != null;
            }

            public void Reset()
            {
                file.Rewind();
            }

            #endregion
        }

        #region IEnumerable<PcapPacket> Members

        public IEnumerator<WiresharkFilePacket> GetEnumerator()
        {
            return new PacketEnumerator(this);
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new PacketEnumerator(this);
        }

        #endregion
    }

最佳答案

你看到 StackOverflowException 因为你在调用自己

public IEnumerator<WiresharkFilePacket> GetEnumerator()
{
    return GetEnumerator();
}

您需要正确地实现一个迭代器才能使其工作。例如:

public IEnumerator<WiresharkFilePacket> GetEnumerator()
{
    for (int i = 0; i < 10; i++)
        yield return new WiresharkFilePacket();
}

您的 WiresharkFile 应该有一些可以迭代的内部集合。无论是您从 pcap 中解析出来并返回的数据包。简单地创建一个 GetEnumerator 方法将无济于事。更多信息,也许您想阅读 How do I implement IEnumerable<T>

关于c# - IEnumerable 无法计算表达式,因为当前线程处于堆栈溢出状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33719634/

相关文章:

c# - 使用变量序列化表达式

c# - 在 .Net 中重定向标准输入和标准输出

c# - 检索可用的连续内存

javascript 属性不可枚举仍然由 for... 在中找到

ruby - 为什么 Ruby 不注入(inject)返回枚举器?

c# - 有 Lambda 脑筋急转弯的好资源吗

c# - IEquatable接口(interface)检查null时做什么

ruby - [1,2,3].to_enum 和 [1,2,3].enum_for 在 Ruby 中的区别

c# - 如何在 C# 中按值获取 Enum 对象?

C# Get 访问器不可访问