我有一个定制的集合,其中有多种对象生成模式。
它可以生成一切,一次一个对象或一次 N 个对象。
我希望可以选择在运行时的生成实现之间进行切换,甚至可以创建新的实现。
我正在寻找具有这种语法的东西:

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

我的问题是:
我不知道有什么作用 EnumerateAs() 返回?我假设它是 IEnumerator,但它仍然是我列表的枚举器吗?
LazyEnumerator 是否继承自 IEnumerator?
它如何知道 myCollection?

有帮助吗?

解决方案

您的回报值 EnumerateAs() 应该 IEnumerable<T>, ,其中t是您集合中包含的对象的类型。我建议阅读更多有关 收益回报, ,因为这可能会帮助您了解枚举的工作原理。没有提供枚举“策略”的默认类,但是您可以通过以各种方式使用基础集合的收益率来轻松实现类似的内容。

从您的问题中不清楚枚举策略将如何与您的收藏类互动。看来您可能会像以下事物一样:

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
    }
}

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

其他提示

我建议您首先创建函数 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

这里,接口和结构的定义完全是通用的;将枚举的每个附加方法添加到类中需要添加一个函数来返回其枚举器,以及一个属性来返回适当类型的 QualifiedEnumerableWrapper。

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

非常灵活。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top