Существуют ли какие-либо инструменты, которые могут помочь нам реорганизовать свойства IEnumerator в IList<T> или аналогичный?

У нас очень старая кодовая база (это на самом деле не ужасное качество). Это восходит к тому времени, когда.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 (не для этой проблемы, а только для общего использования), но, похоже, он не охватывает этот тип сценария.

1 ответ

Похоже, вам нужно вернуть класс, который реализует оба 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 возможно

Да, это некрасиво, но, конечно, могло быть и хуже.

Другие вопросы по тегам