代码之家  ›  专栏  ›  技术社区  ›  the_drow

IEnumerable的多个枚举数

  •  2
  • the_drow  · 技术社区  · 14 年前

    我有一个定制的收藏品,里面有很多种模式的物品。

    我希望可以在运行时在生成的实现之间切换,甚至可以创建新的实现。
    我在找这种语法的东西:

    foreach(var obj in myCollection.EnumerateAs(new LazyEnumerator())
    {
       // ...
    }
    

    我的问题是:
    我不知道这是什么意思 EnumerateAs() 返回?我假设它是IEnumerator,但它仍然是我列表中的枚举器吗?
    LazyEnumerator是否从IEnumerator继承?

    3 回复  |  直到 14 年前
        1
  •  5
  •   the_drow    12 年前

    您的 EnumerateAs() IEnumerable<T> ,其中T是集合中包含的对象的类型。我建议多读一些关于 yield return

    从您的问题中不清楚枚举策略将如何与您的collection类交互。看起来你可能在追求这样的东西:

    public interface IEnumerationStrategy<TCollection, T>
    {
        IEnumerable<T> Enumerate(TCollection source);
    }
    
    public class Quark {}
    
    public class MyCollection
    {
        public IEnumerable<Quark> EnumerateAs(IEnumerationStrategy<MyCollection, Quark> strategy)
        {
            return strategy.Enumerate(this);
        }
    
        //Various special methods needed to implement stategies go here
    }
    
    public class SpecialStrategy : IEnumerationStrategy<MyCollection, Quark>
    {
        public IEnumerable<Quark> Enumerate(MyCollection source)
        {
            //Use special methods to do custom enumeration via yield return that depends on specifics of MyCollection
        }
    }
    

    请注意,还可以用简单的策略替换strategy类 Func<MyCollection, IEnumerable<T>> ,但上面的语法与所需的语法最为匹配。

        2
  •  0
  •   supercat    14 年前

    我建议您首先创建函数GetEnumeratorInFirstStyle、GetEnumeratorInSecondStyle等(当然,要使用适合您的应用程序的名称),然后创建新的结构,例如(vb语法中的示例,但应该很容易转换为C#):

    Class enumTest
        Function GetEnumeratorInFirstStyle() As IEnumerator(Of Integer)
            Return Enumerable.Empty(Of Integer)() ' Real code would do something better
        End Function
        Private Structure FirstStyleEnumerable
            Implements IEnumerable(Of Integer)
    
            Private myEnumTest As enumTest
    
            Public Function GetEnumerator() As System.Collections.Generic.IEnumerator(Of Integer) Implements System.Collections.Generic.IEnumerable(Of Integer).GetEnumerator
                Return myEnumTest.GetEnumeratorInFirstStyle
            End Function
    
            Public Function GetEnumerator1() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
                Return myEnumTest.GetEnumeratorInFirstStyle
            End Function
    
            Sub New(ByVal newEnumTest As enumTest)
                myEnumTest = newEnumTest
            End Sub
        End Structure
        Public ReadOnly Property AsFirstStyleEnumerable As IEnumerable(Of Integer)
            Get
                Return New FirstStyleEnumerable(Me)
            End Get
        End Property
    End Class
    

    请注意,使用的是结构而不是类,因为使用类需要创建一个新的堆对象并为其访问添加额外的间接级别;该结构的真正目的是允许它实现与封装对象“不同”的IEnumerable<T>。顺便说一句,可以将泛型与标记类一起使用,以避免为枚举的每个变体手动定义新的FirstStyleEnumerator结构。不过,我不确定这是更干净还是更混乱。

    Interface IQualifiedEnumerable(Of T, U)
        Function GetEnumerator() As IEnumerable(Of U)
    End Interface
    
    Structure QualifiedEnumerableWrapper(Of T, U)
        Implements IEnumerable(Of U)
        Private myEnumerable As IQualifiedEnumerable(Of T, U)
    
        Public Function GetEnumerator() As System.Collections.Generic.IEnumerator(Of U) Implements System.Collections.Generic.IEnumerable(Of U).GetEnumerator
            Return myEnumerable.GetEnumerator
        End Function
    
        Public Function GetEnumerator1() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
            Return myEnumerable.GetEnumerator
        End Function
    
        Sub New(ByVal newEnumerable As IQualifiedEnumerable(Of T, U))
            myEnumerable = newEnumerable
        End Sub
    End Structure
    
    Class EnumTest2
        Implements IQualifiedEnumerable(Of FirstEnumerationStyle, Integer)
        Implements IQualifiedEnumerable(Of SecondEnumerationStyle, Integer)
    
        Private Class FirstEnumerationStyle     ' Marker classes for generics
        End Class
        Private Class SecondEnumerationStyle
        End Class
    
        Private Function GetFirstStyleEnumerator() As System.Collections.Generic.IEnumerable(Of Integer) Implements IQualifiedEnumerable(Of FirstEnumerationStyle, Integer).GetEnumerator
            Return Enumerable.Empty(Of Integer)()
        End Function
    
        Private Function GetSecondStyleEnumerator() As System.Collections.Generic.IEnumerable(Of Integer) Implements IQualifiedEnumerable(Of SecondEnumerationStyle, Integer).GetEnumerator
            Return Enumerable.Empty(Of Integer)()
        End Function
    
        Public ReadOnly Property AsFirstStyleEnumerable As IEnumerable(Of Integer)
            Get
                Return New QualifiedEnumerableWrapper(Of FirstEnumerationStyle, Integer)
            End Get
        End Property
    
        Public ReadOnly Property AsSecondStyleEnumerable As IEnumerable(Of Integer)
            Get
                Return New QualifiedEnumerableWrapper(Of SecondEnumerationStyle, Integer)
            End Get
        End Property
    End Class
    

    在这里,接口和结构的定义完全是通用的;向类中添加每个额外的枚举方法需要添加一个函数来返回其枚举数,并添加一个属性来返回适当类型的qualifiedEnumerableRapper。

        3
  •  0
  •   Stu Peacock    13 年前
    public class AltEnumerator : System.Collections.IEnumerable
    {
    
        private System.Collections.IEnumerator _base;
    
        public AltEnumerator(System.Collections.IEnumerator _pbase)
        {
            _base = _pbase;
        }
    
    
        #region IEnumerable Members
    
        public System.Collections.IEnumerator GetEnumerator()
        {
            return _base ;
        }
    
        #endregion
    }
    

    在课堂上,你可以:

        public AltEnumerator Iterate(IterDIrection How )
        {
            switch (How)
            {
                case TwoDimArray<T>.IterDIrection.RghtLeftTopBottom:
                    return new AltEnumerator(GetRightLeft());
            }
            return new AltEnumerator(GetEnumerator());
        }
    
        private System.Collections.IEnumerator GetRightLeft()
        {
            for (int cndx = PutSlotArray.GetLength(1) - 1; cndx >= 0; cndx--)
                for (int rndx = 0; rndx < PutSlotArray.GetLength(0); rndx++)
                    if (PutSlotArray[rndx, cndx] != null)
                        yield return PutSlotArray[rndx, cndx];
        }
    
        #region IEnumerable Members
    
        public System.Collections.IEnumerator GetEnumerator()
        {
            foreach (T ps in PutSlotArray)
                if (ps != null)
                    yield return ps;
        }
    
        #endregion