我们有一个非常老的代码库(实际上并不是很糟糕的质量)。它可以追溯到.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(不是针对此问题,而仅用于一般用途),但是它似乎并未涵盖此类情况。

最佳答案

听起来您需要做的是返回一个同时实现IEnumeratorIEnumerable<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();
    }
}


现在,您无需返回IEnumeratorIEnumerable<T>,而可以返回同时执行这两个操作的东西。

请注意,IEnumerator是显式实现的,而IEnumerable<T>是隐式实现的,因此它将鼓励将其用作IEnumerable,同时仍然可以将其用作IEnumerator

是的,这很丑陋,但肯定会更糟。

关于c# - 有没有什么工具可以帮助我们将IEnumerator属性重构为IList <T>或类似的东西?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12982047/

10-17 00:46