我有一个定制的集合,里面有许多对象生成模式。
它可以一次生成所有内容,一个对象或一次生成N个对象
我希望可以选择在运行时在生成的实现之间切换,甚至可以创建新的实现
我正在寻找具有这种语法的东西:
foreach(var obj in myCollection.EnumerateAs(new LazyEnumerator())
{
// ...
}
我的问题是:
我不知道EnumerateAs()
会返回什么?我假设它是IEnumerator,但它仍然是我列表的枚举器吗?
LazyEnumerator是否继承自IEnumerator?
怎么知道myCollection?
答案 0 :(得分: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
}
}
请注意,您也可以使用简单的策略Func<MyCollection, IEnumerable<T>>
替换策略类,但上述内容最接近您所需的语法。
答案 1 :(得分:0)
我建议您首先创建函数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&lt; T&gt;。来自封装的对象。顺便说一下,可以将泛型与标记类一起使用,以避免必须为枚举的每个变体手动定义新的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。
答案 2 :(得分: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
非常灵活。