我们有一个非常古老的代码库(实际上并不是非常糟糕的质量)。它可以追溯到.Net发布之前的时间,我怀疑这是一些奇怪的约定的原因。
无论如何,我们刚刚开始放弃.Net 1.1的支持,并且正在将事情转换为泛型并使用Linq和所有有趣的东西。我们代码库中最讨厌的模式之一是我们会有像
这样的东西private ArrayList mylist;
public IEnumerator MyList
{
get
{
if(mylist==null)
return new EmptyEnumerator.Enumerator;
return mylist.GetEnumerator();
}
}
这种模式特别糟糕,因为它阻止我们简单地执行foreach(var item in MyList)
因为IEnumerator没有实现IEnumerable。相反,我们必须做这样的事情:
IEnumerator enumerator=MyList;
while(enumerator.MoveNext())
{
object item=enumerator.Current;
}
因此,对于重构,我们当然希望使用ReadOnlyCollection<T>
或IList<T>
或类似内容。但要执行此操作,我们必须更新每个对MyList
的引用:
IEnumerator enumerator=MyList;
到
IEnumerator enumerator=MyList.GetEnumerator();
在某些情况下,我们可以对一个属性进行一百多次引用。有没有可以让这更容易的工具?我们最近得到了Resharper(不是针对这个问题,而是仅供一般使用),但它似乎并没有涵盖这种情况。
答案 0 :(得分:4)
你需要做的是返回一个同时实现IEnumerator
和IEnumerable<T>
实际上制作自己的类型实际上并不难:
public class MessedUpIterator<T> : IEnumerable<T>, IEnumerator
{
private IEnumerable<T> source;
private IEnumerator enumerator;
private IEnumerator MyEnumerator
{
get
{
return enumerator ?? source.GetEnumerator();
}
}
public MessedUpIterator(IEnumerable<T> source)
{
this.source = source;
}
public IEnumerator<T> GetEnumerator()
{
return source.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return source.GetEnumerator();
}
object IEnumerator.Current
{
get { return MyEnumerator.Current; }
}
bool IEnumerator.MoveNext()
{
return MyEnumerator.MoveNext();
}
void IEnumerator.Reset()
{
MyEnumerator.Reset();
}
}
现在,您可以返回两者的内容,而不是返回 IEnumerator
或IEnumerable<T>
。
请注意,IEnumerator
是在IEnumerable<T>
隐式实施的情况下明确实施的,因此会鼓励将其用作IEnumerable
,同时仍然将其用作IEnumerator
< EM>可能
是的,这很难看,但肯定会更糟。