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

时间:2015-11-15 12:26:44

标签: c# enumerable

我编写应用Wireshark文件(Pcap,Snopp,Pcapng ...)的应用程序打开此文件并读取所有数据包。

我的基类:

public abstract class WiresharkFile
{
   ...
}

我实施的所有子类IEnumerable

public class Libpcap:WiresharkFile,IDisposable,IEnumerable {     .... }

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

wiresharkFile = new Libpcap(file);

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

foreach (var packet in wiresharkFile)
{

}

所以得到这个错误:

  

foreach语句不能对WiresharkFile类型的变量进行操作'   因为WiresharkFile'不包含公共定义   '的GetEnumerator'

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

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

现在转到此错误StackOverflowException:

  

无法计算表达式,因为当前线程位于堆栈中   溢出状态。

修改

public class Libpcap:WiresharkFile,IDisposable,IEnumerable     {         private BinaryReader binaryReader;         私人版本;         私人uint snaplen;         private int thiszone;         私人uint sigfigs;         private LibpcapLinkType linktype;         私人长基地;         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
}

2 个答案:

答案 0 :(得分:0)

您看到的是11-15 07:19:53.298 2027-2027/? E/SIZE: 0 11-15 07:19:56.746 2027-2027/? E/SIZE: 2 11-15 07:19:57.765 2027-2027/? E/SIZE: 4 ,因为您自称为

StackOverflowException

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

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

你的public IEnumerator<WiresharkFilePacket> GetEnumerator() { for (int i = 0; i < 10; i++) yield return new WiresharkFilePacket(); } 应该有一些可以迭代的内部集合。无论是从pcap解析并返回的数据包。简单地创建WiresharkFile方法将不会做任何事情。或许,您想阅读How do I implement IEnumerable<T>

答案 1 :(得分:0)

如果所有派生类都提供了GetEnumerator()方法,并且您对任何将来的派生类都没有任何问题,但是您的基类无法有意义地定义一个,那么当您将其标记为abstract时。 / p>

public abstract IEnumerator<WiresharkFilePacket> GetEnumerator();

这样就足以在你的基类上实现IEnumerable,你还不需要完整的定义。