2

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

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

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

4

3 回答 3

5

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

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

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 替换 strategy 类Func<MyCollection, IEnumerable<T>>,但上面的语法最符合您的期望。

于 2010-08-25T15:18:19.637 回答
0

我建议您首先创建函数 GetEnumeratorInFirstStyle、GetEnumeratorInSecondStyle 等(当然,使用适合您的应用程序的名称),然后创建类似的新结构(例如 vb 语法,但应该可以轻松转换为 C#):

类 enumTest
    函数 GetEnumeratorInFirstStyle() As IEnumerator(Of Integer)
        Return Enumerable.Empty(Of Integer)() ' 真正的代码会做得更好
    结束功能
    私有结构 FirstStyleEnumerable
        实现 IEnumerable(Of Integer)

        私有 myEnumTest 作为 enumTest

        公共函数 GetEnumerator() As System.Collections.Generic.IEnumerator(Of Integer) 实现 System.Collections.Generic.IEnumerable(Of Integer).GetEnumerator
            返回 myEnumTest.GetEnumeratorInFirstStyle
        结束功能

        公共函数 GetEnumerator1() 作为 System.Collections.IEnumerator 实现 System.Collections.IEnumerable.GetEnumerator
            返回 myEnumTest.GetEnumeratorInFirstStyle
        结束功能

        Sub New(ByVal newEnumTest As enumTest)
            myEnumTest = newEnumTest
        结束子
    末端结构
    公共只读属性 AsFirstStyleEnumerable As IEnumerable(Of Integer)
        得到
            返回新的 FirstStyleEnumerable(Me)
        结束获取
    结束属性
结束类

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

接口 IQualifiedEnumerable(Of T, U)
    函数 GetEnumerator() As IEnumerable(Of U)
端接口

结构 QualifiedEnumerableWrapper(Of T, U)
    实现 IEnumerable(Of U)
    Private myEnumerable As IQualifiedEnumerable(Of T, U)

    公共函数 GetEnumerator() As System.Collections.Generic.IEnumerator(Of U) 实现 System.Collections.Generic.IEnumerable(Of U).GetEnumerator
        返回 myEnumerable.GetEnumerator
    结束功能

    公共函数 GetEnumerator1() 作为 System.Collections.IEnumerator 实现 System.Collections.IEnumerable.GetEnumerator
        返回 myEnumerable.GetEnumerator
    结束功能

    Sub New(ByVal newEnumerable As IQualifiedEnumerable(Of T, U))
        myEnumerable = newEnumerable
    结束子
末端结构

类 EnumTest2
    实现 IQualifiedEnumerable(Of FirstEnumerationStyle, Integer)
    实现 IQualifiedEnumerable(Of SecondEnumerationStyle, Integer)

    Private Class FirstEnumerationStyle ' 泛型的标记类
    结束类
    私有类 SecondEnumerationStyle
    结束类

    私有函数 GetFirstStyleEnumerator() As System.Collections.Generic.IEnumerable(Of Integer) 实现 IQualifiedEnumerable(Of FirstEnumerationStyle, Integer).GetEnumerator
        返回 Enumerable.Empty(Of Integer)()
    结束功能

    私有函数 GetSecondStyleEnumerator() As System.Collections.Generic.IEnumerable(Of Integer) 实现 IQualifiedEnumerable(Of SecondEnumerationStyle, Integer).GetEnumerator
        返回 Enumerable.Empty(Of Integer)()
    结束功能

    公共只读属性 AsFirstStyleEnumerable As IEnumerable(Of Integer)
        得到
            返回新的 QualifiedEnumerableWrapper(Of FirstEnumerationStyle, Integer)
        结束获取
    结束属性

    公共只读属性 AsSecondStyleEnumerable As IEnumerable(Of Integer)
        得到
            返回新的 QualifiedEnumerableWrapper(Of SecondEnumerationStyle, Integer)
        结束获取
    结束属性
结束类

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

于 2011-04-03T17:46:56.530 回答
0
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

非常灵活。

于 2012-06-14T18:01:46.377 回答