2

我们有一个非常古老的代码库(这实际上并不可怕)。它可以追溯到 .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(不是为了这个问题,只是为了一般用途),但它似乎没有涵盖这种类型的场景。

4

1 回答 1

4

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

现在,您可以返回同时执行两者的东西,而不是返回anIEnumeratoran 。IEnumerable<T>

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

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

于 2012-10-19T20:48:56.503 回答