在.NET中可以用 Queue 类型 来定义一个先进先出的无限制的数据链表,但Queue无法限制内部元素长度,它会在数据超过当前长度时自动增长,并且其内部可调用的方法也比较少,不够强大和灵活。

我写这个类型的目的除了补充Queue的缺陷之外,主要是为了限定数据的长度而设计的。

在某些坏境场景下,可能需要一个先进先出的缓存,或者如同一个流水线一般,较旧的数据需要随着时间的推移而舍去,腾出宝贵的内存空间用以存储新的数据,这时候,RunnelList就可以起到大作用了。

''' <summary>流水链</summary>
''' <typeparam name="T"></typeparam>
Public Class RunnelList(Of T)
    Implements IEnumerable

    Dim _count As Integer
    Dim alist As New List(Of T)

    ''' <summary>
    ''' 创建一个流水链
    ''' </summary>
    ''' <param name="count">流水链的长度</param>
    ''' <remarks></remarks>
    Sub New(ByVal count As Integer, ByVal ParamArray items As T())
        If count < 1 Then
            Throw New ArgumentException("数组长度至少为1")
        End If
        If items IsNot Nothing AndAlso items.Length > count Then
            Throw New ArgumentException("数组长度溢出")
        End If

        _count = count
        alist.AddRange(items)

    End Sub

    ''' <summary>增加一个数据到链中</summary>
    ''' <param name="item"></param>
    Public Sub Add(ByVal item As T)
        If alist.Count > _count Then
            alist.RemoveRange(0, alist.Count - _count)
        ElseIf alist.Count = _count Then
            alist.RemoveAt(0)
        End If
        alist.Add(item)
    End Sub

    ''' <summary>添加一组数据到流水链中</summary>
    Public Sub AddRange(ByVal ParamArray items As T())
        If items.Length = 0 Then Return
        If items.Length > _count Then
            Throw New ArgumentException("参数数组长度溢出")
        End If
        alist.RemoveRange(0, items.Length)
        alist.AddRange(items)
    End Sub

    ''' <summary>清除流水链中的全部数据</summary>
    Public Sub Clear()
        alist.Clear()
    End Sub

    ''' <summary>将数据复制到数组中</summary>
    Public Sub CopyTo(ByVal array() As T)
        alist.CopyTo(array)
    End Sub
    Public Sub CopyTo(ByVal array() As T, ByVal arrayIndex As Integer)
        alist.CopyTo(array, arrayIndex)
    End Sub
    Public Sub CopyTo(ByVal index As Integer, ByVal array() As T, ByVal arrayIndex As Integer, ByVal count As Integer)
        alist.CopyTo(index, array, arrayIndex, count)
    End Sub

    ''' <summary>检查某元素是否存在</summary>
    Public Function Contains(ByVal item As T) As Boolean
        Return alist.Contains(item)
    End Function

    ''' <summary>移除指定元素</summary>
    Public Function Remove(ByVal item As T) As Boolean
        Return alist.Remove(item)
    End Function

    ''' <summary>移除指定位置的元素</summary>
    Public Sub RemoveAt(ByVal index As Integer)
        alist.RemoveAt(index)
    End Sub

    ''' <summary>移除一段数据</summary>
    Public Sub RemoveRange(ByVal index As Integer, ByVal count As Integer)
        'If index < 0 OrElse count < 1 Then
        '    Throw New ArgumentException("参数错误")
        'End If
        If count - index > _count Then
            Throw New ArgumentException("删除的参数长度超过限制")
        End If
        alist.RemoveRange(index, count)
    End Sub

    ''' <summary>找到元素的位置</summary>
    Public Function IndexOf(ByVal item As T) As Integer
        Return alist.IndexOf(item)
    End Function

    ''' <summary></summary>
    Public Sub Insert(ByVal index As Integer, ByVal item As T)
        If index < 0 Then
            Throw New ArgumentException("错误的索引位置")
        End If
        If index >= _count Then
            Throw New ArgumentException("索引位置超出流水链长度")
        End If
        alist.Insert(index, item)
        If index = 0 Then
            alist.RemoveAt(1)
        Else
            alist.RemoveAt(0)
        End If
    End Sub

    ''' <summary>将元素压入流水链</summary>
    Public Sub Push(ByVal item As T)
        Add(item)
    End Sub

    ''' <summary>返回第一个有效元素</summary>
    Public Function Peek() As T
        Return alist(0)
    End Function

    ''' <summary>返回第一个有效元素并删除</summary>
    Public Function Pop() As T
        Dim o As T = alist(0)
        alist.RemoveAt(0)
        Return o
    End Function

    ''' <summary>返回流水链的数组</summary>
    Public Function ToArray() As T()
        Return alist.ToArray
    End Function

    ''' <summary>返回或设置流水链长度</summary>
    Public Property Count() As Integer
        Get
            Return _count
        End Get
        Set(ByVal value As Integer)
            If alist.Count > value Then
                ' 在这里默认先进的数据更陈旧,将被舍去
                alist.RemoveRange(0, alist.Count - value)
            End If
            _count = value
        End Set
    End Property

    ''' <summary>返回当前流水链内数据长度</summary>
    Public ReadOnly Property ListCount() As Integer
        Get
            Return alist.Count
        End Get
    End Property

    ''' <summary>直接操作流水链内数据</summary>
    Default Public Property Item(ByVal index As Integer) As T
        Get
            If index < 0 Then
                Throw New ArgumentException("错误的索引位置")
            End If
            If index >= _count Then
                Throw New ArgumentException("索引位置超出流水链长度")
            End If
            Return alist(index)
        End Get
        Set(ByVal value As T)
            If index < 0 Then
                Throw New ArgumentException("错误的索引位置")
            End If
            If index >= _count Then
                Throw New ArgumentException("索引位置超出流水链长度")
            End If
            alist(index) = value
        End Set
    End Property

    Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
        Return New RunnelTEnum(Of T)(alist)
    End Function
End Class




Public NotInheritable Class RunnelTEnum(Of T)
    Implements IEnumerator

    Dim alist As List(Of T)
    Dim position As Integer = -1

    Sub New(ByVal thelist As List(Of T))
        alist = thelist
    End Sub

    Public ReadOnly Property Current() As Object Implements System.Collections.IEnumerator.Current
        Get
            Return alist(position)
        End Get
    End Property

    Public Function MoveNext() As Boolean Implements System.Collections.IEnumerator.MoveNext
        position += 1
        Return (position < alist.Count)
    End Function

    Public Sub Reset() Implements System.Collections.IEnumerator.Reset
        position = -1
    End Sub
End Class